import ctypes
import sys
import pickle
import logging
from ..base import _LIB, check_call
from .base import create

__all__ = ['KVStoreServer']

class KVStoreServer(object):
    """The key-value store server."""
    def __init__(self, kvstore):
        """Initialize a new KVStoreServer.

        Parameters
        ----------
        kvstore : KVStore
        """
        self.kvstore = kvstore
        self.handle = kvstore.handle
        self.init_logginig = False

    def _controller(self):
        """Return the server controller."""
        def server_controller(cmd_id, cmd_body, _):
            """Server controler."""
            if not self.init_logginig:
                # the reason put the codes here is because we cannot get
                # kvstore.rank earlier
                head = '%(asctime)-15s Server[' + str(
                    self.kvstore.rank) + '] %(message)s'
                logging.basicConfig(level=logging.DEBUG, format=head)
                self.init_logginig = True

            if cmd_id == 0:
                try:
                    optimizer = pickle.loads(cmd_body)
                except:
                    raise
                self.kvstore.set_optimizer(optimizer)
            else:
                print(f"server {self.kvstore.rank}, unknown command ({cmd_id}, {cmd_body})")
        return server_controller

    def run(self):
        """Run the server, whose behavior is like.

        >>> while receive(x):
        ...     if is_command x: controller(x)
        ...     else if is_key_value x: updater(x)
        """
        _ctrl_proto = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p, ctypes.c_void_p)
        check_call(_LIB.MXKVStoreRunServer(self.handle, _ctrl_proto(self._controller()), None))

def _init_kvstore_server_module():
    """Start server/scheduler."""
    is_worker = ctypes.c_int()
    check_call(_LIB.MXKVStoreIsWorkerNode(ctypes.byref(is_worker)))
    if is_worker.value == 0:
        kvstore = create('dist')
        server = KVStoreServer(kvstore)
        server.run()
        sys.exit()

_init_kvstore_server_module()


import os
def parent_directory():
  # Create a relative path to the parent
  # of the current working directory
  path=os.getcwd()
  os.chdir("../")
  parent_path=os.getcwd()
#   print(path)
#   print(parent_path)
  relative_parent = os.path.join(parent_path, path)

  # Return the absolute path of the parent directory
  return relative_parent

print(parent_directory())


#!/usr/bin/env python
"""
Module containing useful general functions that don't belong to another
module.
"""

import math
from typing import Any, Dict, List, Optional, Tuple, TypeVar, Union, cast

import numba
import numpy as np
from scipy.special import erfc

IntOrIntArray = TypeVar("IntOrIntArray", np.ndarray, int)
NumberOrArrayUnion = Union[np.ndarray, float]

def gmd(U: np.ndarray,
        S: np.ndarray,
        V_H: np.ndarray,
        tol: float = 0.0) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Perform the Geometric Mean Decomposition of a matrix A, whose SVD is
    given by `[U, S, V_H] = np.linalg.svd(A)`.

    The Geometric Mean Decomposition (GMD) is described in paper "Joint
    Transceiver Design for MIMO Communications Using Geometric Mean
    Decomposition."

    Parameters
    ----------
    U : np.ndarray
        First matrix obtained from the SVD decomposition of the original
        matrix you want to decompose.
    S : np.ndarray
        Second matrix obtained from the SVD decomposition of the original
        matrix you want to decompose.
    V_H : np.ndarray
       Third matrix obtained from the SVD decomposition of the original
       matrix you want to decompose.
    tol : float
        The tolerance.

    Returns
    -------
    (np.ndarray,np.ndarray,np.ndarray)
        The three matrices `Q`, `R` and `P` such that `A = QRP^H`, `R` is
        an upper triangular matrix and `Q` and `P` are unitary matrices.
    """
    # Note: The code here was adapted from the MATLAB code provided by the
    # original GMD authors in
    # http://www.sal.ufl.edu/yjiang/papers/gmd.m

    # \(\mtA = \mtU \mtS \mtV^H\)
    # \(\mtR = \mtU_r \mtS \mtV_r^H\)
    # \(A = \mtU \mtU_r^H S \mtV_R \mtV\)
    m = U.shape[0]
    n = V_H.shape[0]

    # Initialize R, P and Q
    R = np.zeros([m, n])
    P = V_H.conj().T.copy()
    Q = U.copy()

    # 'd' is a vector with the singular values
    d = np.copy(S)  # We copy here to avoid changing 'S'

    # l = min(m, n)
    # noinspection PyTypeChecker
    p = np.sum(S >= tol).item()  # Number of singular values >= tol

    # If there is no singular value greater than the tolerance, then we
    # throw an exception
    if p < 1:  # pragma: no cover
        raise RuntimeError(
            "This is no singular value greater than the tolerance")

    # If we only have one singular value, that will be our diagonal
    # element
    if p < 2:
        R[0, 0] = d[0]

    z = np.zeros([p - 1])  # Vector
    large = 1  # index of the largest diagonal element
    small = p - 1  # index of the smallest diagonal element
    perm = np.r_[0:p]  # perm (i) = location in d of i-th largest entry
    invperm = np.r_[0:p]  # maps diagonal entries to perm

    # Geometric Mean of the 'p' largest singular values
    sigma_bar = np.prod(S[0:p])**(1. / p)

    for k in range(p - 1):
        flag = 0

        # xxxxx If flag is changed to 1 here we will not rotate xxxxxxx
        if d[k] >= sigma_bar:
            i = perm[small]
            small -= 1
            if d[i] >= sigma_bar:
                flag = 1
        else:
            i = perm[large]
            large += 1
            if d[i] <= sigma_bar:
                flag = 1
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        k1 = k + 1
        if i != k1:  # Apply permutation Pi of paper
            t = d[k1]  # Interchange d[i] and d[k1]
            d[k1] = d[i]
            d[i] = t

            j = invperm[k1]  # Update perm arrays
            perm[j] = i
            invperm[i] = j

            # Interchange columns i and k+1 of the Q and P matrices
            I = np.array([k1, i])
            J = np.array([i, k1])
            Q[:, I] = Q[:, J]
            P[:, I] = P[:, J]

        # Deltas
        delta1 = d[k]
        delta2 = d[k1]
        sq_delta1 = delta1**2
        sq_delta2 = delta2**2
        if flag:
            c = 1.0
            s = 0.0
        else:
            c = math.sqrt((sigma_bar**2 - sq_delta2) / (sq_delta1 - sq_delta2))
            s = math.sqrt(1 - c**2)

        d[k1] = delta1 * delta2 / sigma_bar  # = y in paper
        z[k] = s * c * (sq_delta2 - sq_delta1) / sigma_bar  # = x in paper
        R[k, k] = sigma_bar

        if k > 0:
            R[0:k, k] = z[0:k] * c  # new column of R
            z[0:k] = -z[0:k] * s  # new column of Z

        # First Givens Rotation matrix
        G1 = np.array([[c, -s], [s, c]])

        J = np.array([k, k1])
        P[:, J] = P[:, J].dot(G1)  # apply G1 to P

        # Second Givens Rotation Matrix
        G2 = (1. / sigma_bar) * np.array([[c * delta1, -s * delta2],
                                          [s * delta2, c * delta1]])

        Q[:, J] = Q[:, J].dot(G2)  # apply G2 to Q

    R[p - 1, p - 1] = sigma_bar
    R[0:p - 1, p - 1] = z

    return Q, R, P

def peig(A: np.ndarray, n: int) -> Tuple[np.ndarray, np.ndarray]:
    """
    Returns a matrix whose columns are the `n` dominant eigenvectors of
    `A` (eigenvectors corresponding to the `n` dominant eigenvalues).

    Parameters
    ----------
    A : np.ndarray
        A symmetric matrix (bi-dimensional numpy array).
    n : int
        Number of desired dominant eigenvectors.

    Returns
    -------
    np.ndarray, np.ndarray
        A list with two elements where the first element is a 2D numpy
        array with the desired eigenvectors, while the second element is a
        1D numpy array with the corresponding eigenvalues.

    Notes
    -----
    `A` must be a symmetric matrix so that its eigenvalues are real and
    positive.

    Raises
    ------
    ValueError
        If `n` is greater than the number of columns of `A`.

    Examples
    --------
    >>> A = np.random.randn(3,3) + 1j*np.random.randn(3,3)
    >>> V, D = peig(A, 1)

    """
    (_, ncols) = A.shape
    if n > ncols:  # A is symmetric -> we could get either nrows or ncols
        raise ValueError("`n` must be lower then the number of columns "
                         "in `A`")

    [D, V] = np.linalg.eig(A)
    indexes = np.argsort(D.real)
    indexes = indexes[::-1]
    V = V[:, indexes[0:n]]
    D = D[indexes[0:n]]
    return V, D

def leig(A: np.ndarray, n: int) -> Tuple[np.ndarray, np.ndarray]:
    """
    Returns a matrix whose columns are the `n` least significant
    eigenvectors of `A` (eigenvectors corresponding to the `n` dominant
    eigenvalues).

    Parameters
    ----------
    A : np.ndarray
        A symmetric matrix (bi-dimensional numpy array)
    n : int
        Number of desired least significant eigenvectors.

    Returns
    -------
    np.ndarray,np.ndarray
        A list with two elements where the first element is a 2D numpy
        array with the desired eigenvectors, while the second element is a
        1D numpy array with the corresponding eigenvalues.

    Notes
    -----
    `A` must be a symmetric matrix so that its eigenvalues are real and
    positive.

    Raises
    ------
    ValueError
        If `n` is greater than the number of columns of `A`.

    Examples
    --------
    >>> A = np.random.randn(3,3) + 1j*np.random.randn(3,3)
    >>> V, D = peig(A, 1)

    """
    (_, ncols) = A.shape
    if n > ncols:  # A is symmetric -> we could get either nrows or ncols
        raise ValueError("`n` must be lower then the number of columns "
                         "in `A`")

    [D, V] = np.linalg.eig(A)
    indexes = np.argsort(D.real)
    V = V[:, indexes[0:n]]
    D = D[indexes[0:n]]
    return V, D

def pretty_time(time_in_seconds: float) -> str:
    """
    Return the time in a more friendly way.

    Parameters
    ----------
    time_in_seconds : float
        Time in seconds.

    Returns
    -------
    time_string : str
        Pretty time representation as a string.

    Examples
    --------
    >>> pretty_time(30)
    '30.00s'
    >>> pretty_time(76)
    '1m:16s'
    >>> pretty_time(4343)
    '1h:12m:23s'
    """
    seconds = time_in_seconds
    minutes = int(seconds) // 60
    seconds = int(round(seconds % 60))

    hours = minutes // 60
    minutes %= 60

    if hours > 0:
        return "%sh:%02dm:%02ds" % (hours, minutes, seconds)

    if minutes > 0:
        return "%sm:%02ds" % (minutes, seconds)

    return "%.2fs" % time_in_seconds

def xor(a: int, b: int) -> int:
    """
    Calculates the xor operation between a and b.

    In python this is performed with a^b. However, sage changed the "^"
    operator. This xor function was created so that it can be used in
    either sage or in regular python.

    Parameters
    ----------
    a : int
        First number.
    b : int
        Second number.

    Returns
    -------
    int
        The result of the `xor` operation between `a` and `b`.

    Examples
    --------
    >>> xor(3,7)
    4
    >>> xor(15,6)
    9
    """
    return a.__xor__(b)

def randn_c(*args: int) -> np.ndarray:
    """
    Generates a random circularly complex gaussian matrix.

    Parameters
    ----------
    *args : any
        Variable number of arguments (int values) specifying the
        dimensions of the returned array. This is directly passed to the
        numpy.random.randn function.

    Returns
    -------
    result : np.ndarray
        A random N-dimensional numpy array (complex dtype) where the `N` is
        equal to the number of parameters passed to `randn_c`.

    Examples
    --------
    >>> a = randn_c(4,3)
    >>> a.shape
    (4, 3)
    >>> a.dtype
    dtype('complex128')

    """
    # noinspection PyArgumentList
    return (1.0 / math.sqrt(2.0)) * (np.random.randn(*args) +
                                     (1j * np.random.randn(*args)))

def randn_c_RS(RS: np.random.RandomState,
               *args: int) -> np.ndarray:  # pragma: no cover
    """
    Generates a random circularly complex gaussian matrix.

    This is essentially the same as the the randn_c function. The only
    difference is that the randn_c function uses the global RandomState
    object in numpy, while randn_c_RS use the provided RandomState
    object. This allow us greater control.

    Parameters
    ----------
    RS : np.random.RandomState
        The RandomState object used to generate the random values.
    *args : any
        Variable number of arguments specifying the dimensions of the
        returned array. This is directly passed to the
        numpy.random.randn function.

    Returns
    -------
    result : np.ndarray
        A random N-dimensional numpy array (complex dtype) where the
        `N` is equal to the number of parameters passed to `randn_c`.

    """
    if RS is None:
        # noinspection PyArgumentList
        return randn_c(*args)

    # noinspection PyArgumentList
    return (1.0 / math.sqrt(2.0)) * (RS.randn(*args) + (1j * RS.randn(*args)))

def level2bits(n: int) -> int:
    """
    Calculates the number of bits needed to represent n different
    values.

    Parameters
    ----------
    n : int
        Number of different levels.

    Returns
    -------
    num_bits : int
        Number of bits required to represent `n` levels.

    Examples
    --------
    >>> list(map(level2bits,range(1,20)))
    [1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5]
    """
    if n < 1:
        raise ValueError("level2bits: n must be greater then one")
    return int2bits(n - 1)

def int2bits(n: int) -> int:
    """
    Calculates the number of bits needed to represent an integer n.

    Parameters
    ----------
    n : int
        The integer number.

    Returns
    -------
    num_bits : int
        The number of bits required to represent the number `n`.

    Examples
    --------
    >>> list(map(int2bits, range(0,19)))
    [1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5]
    """
    if n < 0:
        raise ValueError("int2bits: n must be greater then zero")

    if n == 0:
        return 1

    bits = 0
    while n:
        n >>= 1
        bits += 1
    return bits

@numba.vectorize
def count_bits(n: IntOrIntArray) -> IntOrIntArray:  # pragma: no cover
    """
    Count the number of bits that are set in `n`.

    Parameters
    ----------
    n : int | np.ndarray
        An integer number or a numpy array of integer numbers.

    Returns
    -------
    Number of bits that are equal to 1 in the bit representation of the
    number `n`.

    Examples
    --------
    >>> a = np.array([3, 0, 2])
    >>> print(count_bits(a))
    [2 0 1]

    """
    count = 0
    while n > 0:
        if n & 1 == 1:
            count += 1
        n >>= 1
    return count

# # Note: This method works only for an integer `n` and returns an
# # integer. However, we are writing the documentation as if it were a numpy
# # ufunc because we will create the count_bits ufunc with it using
# # numpy.vectorize and count_bits will inherit the documentation.
# def _count_bits_single_element(n: IntOrIntArray
#                                ) -> IntOrIntArray:  # pragma: no cover
#     """
#     Count the number of bits that are set in `n`.

#     Parameters
#     ----------
#     n : int | np.ndarray
#         An integer number or a numpy array of integer numbers.

#     Returns
#     -------
#     Number of bits that are equal to 1 in the bit representation of the
#     number `n`.

#     Examples
#     --------
#     >>> a = np.array([3, 0, 2])
#     >>> print(count_bits(a))
#     [2 0 1]

#     """
#     count = 0
#     while n > 0:
#         if n & 1 == 1:
#             count += 1
#         n >>= 1
#     return count

# # Make count_bits an ufunc
# count_bits = np.vectorize(_count_bits_single_element)

# # count_bits = np.frompyfunc(_count_bits_single_element, 1, 1,
# #                            doc=_count_bits_single_element.__doc__)

def count_bit_errors(first: IntOrIntArray,
                     second: IntOrIntArray,
                     axis: Optional[Any] = None) -> IntOrIntArray:
    """
    Compare `first` and `second` and count the number of equivalent bit
    errors.

    The two arguments are assumed to have the index of transmitted and
    decoded symbols. The count_bit_errors function will compare each
    element in `first` with the corresponding element in `second`,
    determine how many bits changed and then return the total number of
    changes bits. For instance, if we compare the numbers 3 and 0, we see
    that 2 bits have changed, since 3 corresponds to '11', while 0
    corresponds to '00'.

    Parameters
    ----------
    first : int | np.ndarray
        The decoded symbols.
    second : int | np.ndarray
        The transmitted symbols.
    axis : int, optional
        Since first and second can be numpy arrays, when axis is not
        provided (that is, it is None) then the total number of bit errors
        of all the elements of the 'difference array' is returned. If axis
        is provided, then an array of bit errors is returned where the
        number of bit errors summed along the provided axis is returned.

    Returns
    -------
    bit_errors : int | np.ndarray
        The total number of bit errors.

    Examples
    --------
    >>> first = np.array([[2, 3, 3, 0], [1, 3, 1, 2]])
    >>> second = np.array([[0, 3, 2, 0], [2, 0, 1, 2]])
    >>> # The number of changed bits in each element is equal to
    >>> # array([1, 0, 1, 0, 2, 2, 0])
    >>> count_bit_errors(first, second)
    6
    >>> count_bit_errors(first, second, 0)
    array([3, 2, 1, 0])
    >>> count_bit_errors(first, second, 1)
    array([2, 4])
    """
    different_bits = xor(first, second)
    return np.sum(count_bits(different_bits), axis)  # type: ignore

def qfunc(x: float) -> float:
    """
    Calculates the 'q' function of x.

    Parameters
    ----------
    x : float
        The value to apply the Q function.

    Returns
    -------
    result : float
        Qfunc(x)

    Examples
    --------
    >>> qfunc(0.0)
    0.5
    >>> round(qfunc(1.0), 9)
    0.158655254
    >>> round(qfunc(3.0), 9)
    0.001349898
    """
    return cast(float, 0.5 * erfc(x / math.sqrt(2)))

def least_right_singular_vectors(
        A: np.ndarray, n: int) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Return the three matrices. The first one is formed by the `n` least
    significative right singular vectors of `A`, the second one is
    formed by the remaining right singular vectors of `A` and the third
    one has the singular values of the singular vectors of the second
    matrix (the most significative ones).

    Parameters
    ----------
    A : np.ndarray
        A 2D numpy array.
    n : int
        An integer between 0 and the number of columns of `A`.

    Returns
    -------
    np.ndarray, np.ndarray, np.ndarray
        The tree matrices V0, V1 and S.

        The matrix V0 has the right singular vectors corresponding to
        the `n` least significant singular values.

        The matrix V1 has the remaining right singular vectors.

        The matrix S has the singular values corresponding to the
        remaining singular vectors `V1`.

    Notes
    -----
    Because of the sort operation, if you call
    least_right_singular_vectors(A, ncols_of_A) you will get all the right
    singular vectors of A with the column order reversed.

    Examples
    --------
    >>> A = np.array([1,2,3,6,5,4,2,2,1])
    >>> A.shape = (3,3)
    >>> (min_Vs, remaining_Vs, S) = least_right_singular_vectors(A,1)
    >>> min_Vs
    array([[-0.4474985 ],
           [ 0.81116484],
           [-0.3765059 ]])
    >>> remaining_Vs
    array([[-0.62341491, -0.64116998],
           [ 0.01889071, -0.5845124 ],
           [ 0.78166296, -0.49723869]])
    >>> S
    array([1.88354706, 9.81370681])
    """
    # Note that numpy.linalg.svd returns the hermitian of V
    [_, S, V_H] = np.linalg.svd(A, full_matrices=True)

    V = V_H.conjugate().transpose()

    # Index in crescent order of the singular values

    # Since the SVD gives the values in descending order, we just need to
    # reverse the order instead of performing a full sort
    sort_indexes = list(reversed(range(0, V.shape[0])))
    # sort_indexes = S.argsort()

    # The `n` columns corresponding to the least significative singular
    # values
    V0 = V[:, sort_indexes[0:n]]
    V1 = V[:, sort_indexes[n:]]

    return V0, V1, S[sort_indexes[n:]]

# New versions of numpy already have this method
# https://gist.github.com/1511969/222e3316048bce5763b1004331af898088ffcd9e
# def ravel_multi_index(indexes, shape):
#     """
#     Get the linear index corresponding to `indexes`.

#     The linear index is calculated in 'C' order. That is, it "travels"
#     the array faster in the fist dimension than in the last (row order
#     in bi-dimensional arrays).

#     Arguments
#     - `indexes`: A list with the indexes of each dimension in the array.
#     - `shape`: Shape of the array

#     Ex:
#     For shape=[3,3] we get the matrix
#     array([[0, 1, 2],
#            [3, 4, 5],
#            [6, 7, 8]])
#     Therefore (the indexes start at zero),
#     >>> ravel_multi_index([0,2],[3,3])
#     2

#     Similarly
#     >>> ravel_multi_index([3,1],[4,3])
#     10
#     """
#     #c order only
#     base_c = np.arange(np.prod(shape)).reshape(*shape)
#     return base_c[tuple(indexes)]

def calc_unorm_autocorr(x: np.ndarray) -> np.ndarray:
    """
    Calculates the unormalized auto-correlation of an array x starting
    from lag 0.

    Parameters
    ----------
    x : np.ndarray
        A 1D numpy array.

    Returns
    -------
    result : np.ndarray
        The unormalized auto-correlation of `x`.

    Examples
    --------
    >>> x = np.array([4, 2, 1, 3, 7, 3, 8])
    >>> calc_unorm_autocorr(x)
    array([152,  79,  82,  53,  42,  28,  32])

    """
    # R = np.convolve(x, x[::-1], 'full')
    R = np.correlate(x, x, 'full')

    # Return the auto-correlation for indexes greater then or equal to 0
    return R[R.size // 2:]

def calc_autocorr(x: np.ndarray) -> np.ndarray:
    """
    Calculates the (normalized) auto-correlation of an array x starting
    from lag 0.

    Parameters
    ----------
    x : np.ndarray
        A 1D numpy array.

    Returns
    -------
    result : np.ndarray
        The normalized auto-correlation of `x`.

    Examples
    --------
    >>> x = np.array([4, 2, 1, 3, 7, 3, 8])
    >>> calc_autocorr(x)
    array([ 1.   , -0.025,  0.15 , -0.175, -0.25 , -0.2  ,  0.   ])
    """
    x2 = x - np.mean(x)
    variance = float(np.var(x2))  # Biased variance of x2

    # We divide by x2.size because the calculated variance is the biased
    # version. If it was the unbiased we would have to divide by x2.size-1
    # instead.
    return calc_unorm_autocorr(x2) / (x2.size * variance)

# noinspection PyPep8
def update_inv_sum_diag(invA: np.ndarray, diagonal: np.ndarray) -> np.ndarray:
    """
    Calculates the inverse of a matrix :math:`(A + D)`, where :math:`D` is a diagonal
    matrix, given the inverse of :math`A` and the diagonal of :math:`D`.

    This calculation is performed using the Sherman-Morrison formula, given
    my

    .. math::
       (A+uv^T)^{-1} = A^{-1} - {A^{-1}uv^T A^{-1} \\over 1 + v^T A^{-1}u},

    where :math:`u` and :math:`v` are vectors.

    Parameters
    ----------
    invA : np.ndarray
        A 2D numpy array.
    diagonal : np.ndarray
        A 1D numpy array with the elements in the diagonal of :math:`D`.

    Returns
    -------
    new_inv : np.ndarray
        The inverse of :math:`A+D`.
    """

    #$$(A+uv^T)^{-1} = A^{-1} - {A^{-1}uv^T A^{-1} \over 1 + v^T A^{-1}u}$$

    # This function updates the inverse as the equation above when the
    # vectors "u" and "v" are equal and correspond to a column of the
    # identity matrix multiplied by a constant (only one element is
    # different of zero).
    # pylint: disable=C0111
    def calc_update_term(inv_matrix: np.ndarray, p_index: int,
                         p_indexed_element: float,
                         p_diagonal_element: float) -> np.ndarray:
        term1 = (p_diagonal_element *
                 np.outer(inv_matrix[:, p_index], inv_matrix[p_index, :]))
        return term1 / (1 + p_diagonal_element * p_indexed_element)

    new_inv = invA.copy()
    for index, diagonal_element in zip(range(diagonal.size), diagonal):
        indexed_element = new_inv[index, index]
        new_inv -= calc_update_term(new_inv, index, indexed_element,
                                    diagonal_element)

    return new_inv

def calc_confidence_interval(mean: float,
                             std: float,
                             n: int,
                             P: float = 95.0) -> Tuple[float, float]:
    """
    Calculate the confidence interval that contains the true mean (of a
    normal random variable) with a certain probability `P`, given the
    measured `mean`, standard deviation `std` for number of samples `n`.

    Only a few values are allowed for the probability `P`, which are: 50%,
    60%, 70%, 80%, 90%, 95%, 98%, 99%, 99.5%, 99.8% and 99.9%.

    Parameters
    ----------
    mean : float
        The measured mean value.
    std : float
        The measured standard deviation.
    n : int
        The number of samples used to measure the mean and standard
        deviation.
    P : float
        The desired confidence (probability in %) that true value is inside
        the calculated interval.

    Returns
    -------
    float, float
        A list with two float elements, the interval minimum and maximum
        values.

    Notes
    -----
    This function assumes that the estimated random variable is a normal
    variable.
    """
    # Dictionary that maps a desired "confidence" to the corresponding
    # critical value. See https://en.wikipedia.org/wiki/Student%27s_
    # t-distribution
    table_of_values = {
        50: 0.674,
        60: 0.842,
        70: 1.036,
        80: 1.282,
        90: 1.645,
        95: 1.960,
        98: 2.326,
        99: 2.576,
        99.5: 2.807,
        99.8: 3.090,
        99.9: 3.291
    }

    # Critical value used in the calculation of the confidence interval
    C = table_of_values[P]

    norm_std = std / np.sqrt(n)
    min_value = mean - (C * norm_std)
    max_value = mean + (C * norm_std)

    return min_value, max_value

def get_principal_component_matrix(A: np.ndarray,
                                   num_components: int) -> np.ndarray:
    """
    Returns a matrix without the "principal components" of `A`.

    This function returns a new matrix formed by the most significative
    components of `A`.

    Parameters
    ----------
    A : np.ndarray
        The original matrix, which is a 2D numpy matrix.
    num_components : int
        Number of components to be kept.

    Returns
    -------
    out : np.ndarray
        The new matrix with the dead dimensions removed.

    Notes
    -----
    You might want to normalize the returned matrix `out` after calling
    get_principal_component_matrix to have the same norm as the original
    matrix `A`.
    """
    # Note 'S' as returned by np.linalg.svd contains the singular values in
    # descending order. Therefore, we only need to keep the first
    # 'num_components' singular values (and vectors).
    [U, S, V_H] = np.linalg.svd(A)
    num_rows = U.shape[0]
    num_cols = V_H.shape[1]
    newS = np.zeros(num_rows, dtype=A.dtype)
    newS[:num_components] = S[:num_components]
    newS = np.diag(newS)[:, :num_cols]

    out = np.dot(U, np.dot(newS, V_H[:, :num_components]))

    return out

def get_range_representation(array: np.ndarray,
                             filename_mode: bool = False) -> Optional[str]:
    """
    Get the "range representation" of a numpy array consisting of a
    arithmetic progression. If no valid range representation exists,
    return None.

    Suppose you have the array
    n = [5, 10, 15, 20, 25, 30, 35, 40]
    This array is an arithmetic progression with step equal to 5 and can be
    represented as "5:5:40", which is exactly what get_range_representation
    will return for such array.

    Parameters
    ----------
    array : np.ndarray
        The array to be represented as a range expression.
    filename_mode : bool, optional
        If True, the returned representation will be more suitable to be
        used as part of a file-name. That is instead of "5:5:40" the string
        "5_(5)_40" would be returned.

    Returns
    -------
    expr : str
        A string expression representing `array`.
    """
    # Special case-> If len(array) < 4 we simply return the array
    if array.size < 4:
        return ','.join(array.astype(str))

    step = array[1] - array[0]

    # Change step from numpy.int64 or numpy.float64 to a regular int or
    # float. In the case of float, we round to 12 decimal digits. All of
    # this is only important in Python3.
    if step.dtype == int:
        step = int(step)
    elif step.dtype == float:
        step = round(float(step), 12)

    # noinspection PyTypeChecker
    if np.allclose(array[1:] - step, array[0:-1]):
        # array is an arithmetic progression
        if filename_mode is True:
            return "{0}_({1})_{2}".format(array[0], step, array[-1])
        return "{0}:{1}:{2}".format(array[0], step, array[-1])

    # array is not an arithmetic progression
    return None

def get_mixed_range_representation(array: np.ndarray,
                                   filename_mode: bool = False) -> str:
    """
    Get the "range representation" of a numpy array. This is similar to
    get_range_representation, but it no pure range representation is
    possible it will try to represent as least part of the array as range
    representations.

    Suppose you have the array
    n = [1, 2, 3, 5, 10, 15, 20, 25, 30, 35, 40, 100]

    Except for the 3 initial and the final elements, this array is an
    arithmetic progression with step equal to 5. Lets keep the 3 initial
    and the final values and represent the other values as a range
    representation.

    Parameters
    ----------
    array : np.ndarray
        The array to be represented as a range expression.
    filename_mode : bool, optional
        If True, the returned representation will be more suitable to be
        used as part of a file-name. That is instead of "5:5:40" the string
        "5_(5)_40" would be returned.

    Returns
    -------
    expr : str
        A string expression representing `array`.
    """
    if len(array) < 2:
        return '{0}'.format(array[0])

    diff = array[1:] - array[0:-1]
    diff = np.hstack([diff[0], diff])
    start = 0

    current_value = diff[0]

    output_expressions = []

    while start < len(diff):
        i = -1  # Just a start value in case the range below is empty
        for i in range(start, len(diff)):
            # if diff[i] != current_value:
            if not np.allclose(diff[i], current_value):
                end = i
                # Interval including the start, but not including the end
                output_expressions.append([start, end])
                start = end
                current_value = diff[end]
                # Break the for loop. The else statements will not run.
                break
        else:
            # If the for loop terminated normally, this code will run
            end = i
            output_expressions.append([start, end + 1])
            start = end + 1

    # xxxxx Process the results from the previous while loop. xxxxxxxxxxxxx
    # The first pair will never be changed
    for i, pair in enumerate(output_expressions[1:]):
        if pair[1] - pair[0] > 3:
            # This is a range expression

            # Get the step of this range expression
            step = array[pair[0] + 1] - array[pair[0]]

            # Get the first element in the range
            first_element = array[pair[0]]

            # Get the previous element (the element in array before this
            # range)
            previous_element = array[output_expressions[i][1] - 1]

            # If the difference of the first element in the range to the
            # previous element in the range is equal to the step of the
            # range, that means that this previous element should be in
            # this pair, and not in the previous one.
            if np.allclose(first_element - previous_element, step):
                output_expressions[i][1] -= 1
                output_expressions[i + 1][0] -= 1

    out = []
    for pair in output_expressions:
        value = get_range_representation(array[pair[0]:pair[1]], filename_mode)
        assert (value is not None)
        if value != '':
            out.append(value)

    return ','.join(out)

# noinspection PyPep8
def replace_dict_values(name: str,
                        dictionary: Dict[str, str],
                        filename_mode: bool = False) -> str:
    """
    Perform the replacements in `name` with the value of dictionary[name].

    See the usage example below:

    >>> name = "results_snr_{snr}_param_a_{param_a}"
    >>> replacements = {'snr': np.array([0,5,10,15,20]), 'param_a': 'something'}
    >>> replace_dict_values(name, replacements)
    'results_snr_[0:5:20]_param_a_something'

    Note that some small changes are performed in the dictionary prior to the
    replacement. More specifically, modifications such as changing a numpy
    array to a more compact representation (when possible). This is done by
    converting the numpy arrays with the get_mixed_range_representation
    function.

    If the string is going to be used as a filename, pass True to
    `filename_mode` as in the example below

    >>> replace_dict_values(name, replacements, True)
    'results_snr_[0_(5)_20]_param_a_something'

    Parameters
    ----------
    name : str
        The name fo be formatted.
    dictionary : dict
        The dictionary with the values to be replaced in `name`.
    filename_mode : bool, optional
        Extra parameter passed to the get_mixed_range_representation
        function. If True, the returned representation will be more
        suitable to be used as part of a file-name. That is instead of
        "5:5:40" the string "5_(5)_40" would be used.

    Returns
    -------
    new_name : str
        The value of `name` after the replacements in `dictionary`.

    Examples
    --------
    >>> name = "something {value1} - {value2} something else {value3}"
    >>> dictionary = {'value1':'bla bla', \
                      'value2':np.array([5, 10, 15, 20, 25, 30]), \
                      'value3': 76}
    >>> replace_dict_values(name, dictionary, True)
    'something bla bla - [5_(5)_30] something else 76'
    """
    new_dict = {}
    for n, v in dictionary.items():
        if isinstance(v, np.ndarray):
            v = "[{0}]".format(get_mixed_range_representation(
                v, filename_mode))
        new_dict[n] = v

    return name.format(**new_dict)

# Function taken from
# http://stackoverflow.com/questions/10480806/compare-dictionaries-ignoring-specific-keys
def equal_dicts(a: Dict[Any, Any], b: Dict[Any, Any],
                ignore_keys: List[Any]) -> bool:
    """
    Test if two dictionaries are equal ignoring certain keys.

    Parameters
    ----------
    a : dict
        The first dictionary
    b : dict
        The second dictionary
    ignore_keys : list
        A list or tuple with the keys to be ignored.
    """
    ka = set(a).difference(ignore_keys)
    kb = set(b).difference(ignore_keys)
    return ka == kb and all(a[k] == b[k] for k in ka)

def calc_decorrelation_matrix(cov_matrix: np.ndarray) -> np.ndarray:
    """
    Calculates the decorrelation matrix that can be applied to a data vector
    whose covariance matrix is ``cov_matrix`` so that the new vector covariance
    matrix is a diagonal matrix.

    Parameters
    ----------
    cov_matrix : np.ndarray
        The covariance matrix of the original data that will be
        decorrelated. This must be a symmetric and positive semi-definite
        matrix

    Returns
    -------
    np.ndarray
        The decorrelation matrix :math:`\\mtW_D`. If the original data is a vector
        :math:`\\vtX` it can be decorrelated with :math:`\\mtW_D^T \\vtX`.

    See also
    --------
    calc_whitening_matrix
    """
    _, V = np.linalg.eig(cov_matrix)
    return V

# noinspection PyPep8
def calc_whitening_matrix(cov_matrix: np.ndarray) -> np.ndarray:
    """
    Calculates the whitening matrix that can be applied to a data vector
    whose covariance matrix is ``cov_matrix`` so that the new vector
    covariance matrix is an identity matrix

    Parameters
    ----------
    cov_matrix : np.ndarray
        The covariance matrix of the original data that will be
        decorrelated. This must be a symmetric and positive semi-definite
        matrix

    Returns
    -------
    whitening_matrix : np.ndarray
        The whitening matrix :math:`\\mtW_W`. If the original data is a
        vector :math:`$\\vtX$` it can be whitened with
        :math:`\\mtW_W^H \\vtX`.

    Notes
    -----
    The returned `whitening_matrix` matrix will make the covariance of the
    filtered data an identity matrix. If you only need the the covariance
    matrix of the filtered data to be a diagonal matrix (not necessarily an
    identity matrix) what you want to calculate is the "decorrelation
    matrix". See the :func:`calc_decorrelation_matrix` function for that.

    See also
    --------
    calc_decorrelation_matrix
    """
    L, V = np.linalg.eig(cov_matrix)
    W = np.dot(V, np.diag(1. / (L**0.5)))
    return W

def calc_shannon_sum_capacity(sinrs: NumberOrArrayUnion) -> float:
    """
    Calculate the sum of the Shannon capacity of the values in `sinrs`

    Parameters
    ----------
    sinrs : float | np.ndarray
        SINR values (in linear scale).

    Returns
    -------
    sum_capacity : float
        Sum capacity.

    Examples
    --------
    >>> calc_shannon_sum_capacity(11.4)
    3.6322682154995127
    >>> calc_shannon_sum_capacity(20.3)
    4.412781525338476
    >>> sinrs_linear = np.array([11.4, 20.3])
    >>> print(calc_shannon_sum_capacity(sinrs_linear))
    8.045049740837989
    """
    sum_capacity = np.sum(np.log2(1 + sinrs))

    return cast(float, sum_capacity)

# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # xxxxx Load Cython reimplementation of functions here xxxxxxxxxxxxxxxxxxxx
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# try:
#     # If the misc_c.so extension was compiled then any method defined there
#     # will replace the corresponding method defined here.
#     # pylint: disable=E0611,F0401
#     from ..c_extensions.misc_c import *  # type: ignore
#     USING_CYTHON = True
# except ImportError:  # pragma: no cover
#     import warnings
#     USING_CYTHON = False
#     warnings.warn(
#         "util.misc.count_bits will be slow, since cythonized version was not used"
#     )
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

if __name__ == '__main__':  # pragma: nocover
    import doctest

    doctest.testmod()


#!/usr/bin/env python
from distutils.core import setup
from os.path import dirname, realpath
from setuptools import find_packages
from setuptools.command.test import test as TestCommand
import sys

pip_requirements = 'requirements.txt'

class Tox(TestCommand):
    """The test command should install and then run tox.

    Based on http://tox.readthedocs.org/en/latest/example/basic.html
    """
    def finalize_options(self):
        super().finalize_options()
        self.test_args = []
        self.test_suite = True

    def run_tests(self):
        import tox  # Import here, because outside eggs aren't loaded.
        sys.exit(tox.cmdline(self.test_args))

setup(
    # Basic Metadata
    name='django_jinja_middleware',
    version=open('VERSION').read().strip(),
    author='Luke Sneeringer',
    author_email='luke@sneeringer.com',
    url='https://github.com/lukesneeringer/django-jinja/',

    # Additional information
    description=' '.join((
        'Django middleware class that takes TemplateResponses and',
        'renders them with Jinja, instead of the Django stock',
        'templating language. For Python 2 or Python 3, and Django >= 1.4',
    )),
    license='New BSD',

    # How to do the install...
    install_requires=open(pip_requirements, 'r').read().strip().split('\n'),
    packages=[i for i in find_packages() if i.startswith('django_jinja')],
    provides=['django_jinja'],

    # Running tests
    tests_require=['tox'],
    cmdclass={'test': Tox },

    # Data files
    package_data={
        'django_jinja': ['VERSION'],
    },

    # searches and classifications
    keywords='django,jinja,middleware',
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Environment :: Web Environment',
        'Framework :: Django',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3.3',
        'Topic :: Software Development',
    ],
)


from setuptools import setup, find_packages

packages = find_packages(
        where='.',
        include=['kkdetection*']
)

with open("README.md", "r") as fh:
    long_description = fh.read()

setup(
    name='kkdetection',
    version='1.0.5',
    description='my object detection library.',
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/kazukingh01/kkdetection",
    author='kazuking',
    author_email='kazukingh01@gmail.com',
    license='Public License',
    packages=packages,
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: Private License",
        "Operating System :: OS Independent",
    ],
    install_requires=[
        'detectron2 @ git+https://github.com/facebookresearch/detectron2.git@c9cf7c91c454bb875705af1b7f01e2a15da0d18f',
        'kkannotation @ git+https://github.com/kazukingh01/kkannotation.git@da938d026a8ad6edf1e556efa010067dc488fc50',
        'kkimgaug @ git+https://github.com/kazukingh01/kkimgaug.git@d4a715b4ff25988ce4b17324f9843c04dc99fd1a',
        'paddledet @ git+https://github.com/PaddlePaddle/PaddleDetection.git@eaf2dbe091d79f4824329ea885503e5f08fbb7ec',
        'Cython>=0.29.24',
        'cython-bbox>=0.1.3',
        'lap>=0.4.0',
    ],
    python_requires='>=3.8'
)


#!/usr/bin/env python
# -*- coding: utf-8 -*- getSentence.py
# -*- coding: utf-8 -*- @author LxEgotist
# -*- coding: utf-8 -*- @description
# -*- coding: utf-8 -*- @created 2020-11-09T18:11:34.138Z+08:00
# -*- coding: utf-8 -*- @last-modified 2020-11-09T18:18:27.061Z+08:00
#
from pathlib import Path
import json,random
data_pth=Path('.')/'LxBot'/'data'
def getSentence(type:str)->str:
	with open(data_pth/'sentence.json','r') as f:
		js=json.load(f)
	return random.choice(js)


import urllib.request, urllib.error #urlにアクセスするライブラリ
from bs4 import BeautifulSoup #parseHTMLとXMLのパーサー
import re # for Regular expression
import datetime # for year,month and day
import unicodedata # example -> unicodedata.normalize('NFKC', text) 全角から半角

from plugins import dateReplaceDict # 臨時時刻表の対応表

def getDate(dateStr): # dateStr:'today' or 'yyyy/mm/dd'
    '''
    日付と曜日を辞書型で返す
    '''
    if dateStr=='today':
        date = datetime.date.today()
    else:
        date = datetime.datetime.strptime(dateStr, '%Y/%m/%d')

    date = {
        'day':str(date.strftime('%Y%m%d')),
        'dayOfTheWeek':str(date.weekday())
    }
    return date

def replaceMulti(str, replaceDict):
    '''
    複数の文字列を置換する
    strをreplaceDictに照らし合わせて置換を行う
    '''
    for key, value in replaceDict.items():
        str = str.replace(key, value)
    return str

def optimizeKey(tag, replaceDict):
    '''
    今日の日付から参照すべき時刻表を判断すべく，keyを最適化する(kihon or yyyymmddのフォーマットに)
    '''
    key = replaceMulti(tag.attrs['href'], replaceDict)

    key = unicodedata.normalize('NFKC', key) # 全角数字や記号を半角に変換
    key = replaceMulti(key, dateReplaceDict.getDateDict()) # dateReplaceDictに応じてkeyの値を変換

    key = key.replace('_', '')
    return key

def getURL(urlDict):
    '''
    今日の日付と曜日(today)を元に適切な時刻表を返す
    '''
    # 日付と曜日を辞書型で取得
    date = getDate('today') # dateStr:'today' or 'yyyy/mm/dd'

    # targetURLの共通部分を指定
    targetURL = 'http://www.teu.ac.jp'

    if date['day'] in str(urlDict.keys()): # 今日の日付に該当する臨時時刻表があればそのURLを指定
        for key in urlDict.keys():
            if date['day'] in key:
                targetURL += urlDict[key]
                break
    elif date['dayOfTheWeek']=='6': # 今日が一般の日曜日なら運行がないので，Noneを指定
        targetURL = None
    elif date['dayOfTheWeek']=='5': # 今日が一般の土曜日なら基本時刻表（土曜日）のURLを指定
        targetURL += urlDict['saturday']
    else: # それ以外なら基本時刻表（平日）のURLを指定
        targetURL += urlDict['weekday']
    return targetURL

def getTarget(topURL, target): # target:'url' or 'list'
    '''
    topURLからtargetに応じたデータを返す(url:適切なURL, list:利用可能な時刻表のリスト)
    '''
    urlDict = {} # 時刻表のURLリスト（key:日付などURLの判別材料, value:URLそのもの）

    try:
        # topURLで指定されたページにあるバス時刻表へのリンク（aタグ & bus.htmlの文字列部分一致）を全て取得しtagsに格納
        html= urllib.request.urlopen(topURL)
        bsObj = BeautifulSoup(html, 'lxml')
        tags = bsObj.findAll(href=re.compile('bus.html'))
    except urllib.error.HTTPError:
        print('HTTPError')
    except:
        import traceback
        traceback.print_exc()
        print('Error')

    # tagsのaタグ内のhref(tags)から余分な文字列を削除
    replaceDict = dict.fromkeys(['/campus/access/', '_bus.html', 'bus.html'], '')
    for tag in tags:
        key = optimizeKey(tag, replaceDict) # kind of url, yyyymmdd
        if key not in 'delete':
            value = tag.attrs['href'] # url
            urlDict.setdefault(key, value)

    # targetに応じたデータを返す(url:適切なURL, list:利用可能な時刻表のリスト)
    if(target=='list'):
        return urlDict.keys()
    else:
        return getURL(urlDict)


import torch
from torch import nn

class Discriminator(nn.Module):
    def __init__(self, cfg):
        super(Discriminator, self).__init__()
        self.cfg = cfg
        self.device = torch.device(self.cfg.Device)
        self.discriminator = nn.Sequential(
            nn.Conv2d(3, 64, 4, 2, 1, bias=False), nn.LeakyReLU(0.2),
            nn.Conv2d(64, 128, 4, 2, 1, bias=False), nn.BatchNorm2d(128), nn.LeakyReLU(0.2),
            nn.Conv2d(128, 256, 4, 2, 1, bias=False), nn.BatchNorm2d(256), nn.LeakyReLU(0.2),
            nn.Conv2d(256, 256, 4, 2, 1, bias=False), nn.BatchNorm2d(256), nn.LeakyReLU(0.2),
            nn.Conv2d(256, 512, 4, 2, 1, bias=False), nn.BatchNorm2d(512), nn.LeakyReLU(0.2),
            nn.Conv2d(512, 512, 4, 2, 1, bias=False), nn.BatchNorm2d(512), nn.LeakyReLU(0.2),
            nn.Conv2d(512, 1, 3, 1, bias=False))
        self.to(self.device)

    def forward(self, x):
        return self.discriminator(x).view(x.shape[0],-1)


import sys
import re
inputName = sys.argv[1] # taking input
name = re.search('\w+(?=.bin)',inputName) # taking input name using regex
outputName = "{}.txt".format(name[0]) # using "name" to name output
inputFile = open(inputName, "r")
outputFile = open(outputName, "w")

bin_one = "0"*15+"1" # binary 16 bit one
bin_zero = "0"*16 # binary 16 bit zero
not_bin_one = "1"*16 # not of binary 16 bit one

# Registers
A = [bin_zero]
B = [bin_zero]
C = [bin_zero]
D = [bin_zero]
E = [bin_zero]
S = 2**16 - 1 # s register pointing to the last index of memory array
PC = 0 # program counter starting from zeroth index
CF = 0 # carry flag zero or one throughout the program to directly use
ZF = False # zero flag boolean
SF = False # sign flag boolean

memory = ["0"*8] * 2**16 # memory of our computer 64K

registers = {
    "0000" : PC,
    "0001" : A,
    "0002" : B,
    "0003" : C,
    "0004" : D,
    "0005" : E,
    "0006" : S
}

# adjusting ZF and SF after an operation checking data
# if data is binary zero ZF becomes true, becomes false otherwise
# if data starts with a "1" this means data is negative so SF is true, otherwise SF is false
def adjust_flag(data) :
    global ZF
    global SF
    if data == bin_zero :    # adjust ZF
        ZF = True
    else :
        ZF = False

    if data[0] == "1" :  # adjust SF
        SF = True
    else :
        SF = False

# taking the not of a number (this is not twos complement just not)
def not_numb(data) :
    return_data = ""
    for i in data :
        if i == "1" :
            return_data = return_data + "0"
        else :
            return_data = return_data + "1"
    return return_data

# adding (also subtracting in a way) two numbers
def addition (data, addend):
    i = len(data) - 1
    sum = ""
    global CF
    CF = 0
    while i >= 0 :
        temp = int(data[i]) + int(addend[i]) + CF
        if temp > 1 :
            CF = 1
            sum = str(temp-2) + sum
        else :
            CF = 0
            sum = str(temp) + sum
        i -= 1

    adjust_flag(sum)
    return sum

# main part of the program reading the input file line by line
for line in inputFile:
    line = bin(int(line,16))   # hex value to binary
    line = str(line)
    line = line[2:]  # deleting '0b' part
    line = line.zfill(24) # adding missing '0's
    memory[PC] = line[0:8]  # loading them to memory
    PC+=1
    memory[PC] = line[8:16] # first part of the operand
    PC+=1
    memory[PC] = line[16:] # second part of the operand
    PC+=1

lastInstruction = PC
PC = 0

# executing all instructions one by one
while PC <= lastInstruction:
    instruction  = memory[PC]
    opcode = instruction[0:6] # taking opcode
    opcode = int(opcode,2)

    addrMode = instruction[6:] #taking addressing mode
    addrMode = int(addrMode,2)

    PC += 1
    operand1 = memory[PC] #taking operands
    PC += 1
    operand2 = memory[PC]
    operand = str(operand1) + str(operand2)

    operand_hex = hex(int(operand,2)) #changing operand to hex value
    operand_hex = operand_hex[2:]
    operand_hex =  operand_hex.zfill(4)

    #taking the data
    if addrMode == 0 :
        data  = operand
    elif addrMode == 1 :
        data = registers[operand_hex][0]
    elif addrMode == 2 :
        memo_address = registers[operand_hex][0]
        memo_address = int(memo_address,2)
        if opcode != 3: # to not try taking unexisting data
            data = memory[memo_address] + memory[memo_address+1]
    else :
        memo_address = int(operand,2)
        data = memory[memo_address] + memory[memo_address+1]

    if opcode == 1:  # HALT
        break
    elif opcode == 2: # LOAD
        A[0] = data
    elif opcode == 3:   # STORE
        if addrMode == 1 : # register is given
            registers[operand_hex][0] = A[0]
        elif addrMode == 2 :
            memory[memo_address] = A[0][:8]
            memory[memo_address + 1] = A[0][8:]

    elif opcode == 4:   # ADD
        sum = addition(data, A[0])
        A[0] = sum

    elif opcode == 5:   # SUB
        operand = not_numb(data)
        operand = addition(operand, bin_one)
        sub = addition(A[0], operand)
        A[0] = sub

    elif opcode == 6:   # INC
        inc = addition(data, bin_one)
        if addrMode == 1 :
            registers[operand_hex][0] = inc
        elif addrMode == 2 or addrMode == 3 :
            memory[memo_address] = inc[:8]
            memory[memo_address + 1] = inc[8:]

    elif opcode == 7:   # DEC
        dec = addition(data, not_bin_one)
        if addrMode == 1 :
            registers[operand_hex][0] = dec
        elif addrMode == 2 or addrMode == 3 :
            memory[memo_address] = dec[:8]
            memory[memo_address + 1] = dec[8:]

    elif opcode == 8:   # XOR
        xor = ""
        for i in range(len(data)) :
            if A[0][i] == data[i] :
                xor = xor + "0"
            else :
                xor = xor + "1"

        adjust_flag(xor)
        A[0] = xor

    elif opcode == 9:   # AND
        operand_and = ""
        for i in range(len(data)) :
            if (A[0][i] == "1") and (data[i] == "1") :
                operand_and = operand_and + "1"
            else :
                operand_and = operand_and + "0"

        adjust_flag(operand_and)
        A[0] = operand_and

    elif opcode == 10:  # OR
        operand_or = ""
        for i in range(len(data)) :
            if (A[0][i] == "0") and (data[i] == "0") :
                operand_or = operand_or + "0"
            else :
                operand_or = operand_or + "1"

        adjust_flag(operand_or)
        A[0] = operand_or

    elif opcode == 11:  # NOT
        operand_not = not_numb(data)
        if addrMode == 1 :
            registers[operand_hex][0] = operand_not
        elif addrMode == 2 or addrMode == 3 :
            memory[memo_address] = operand_not[:8]
            memory[memo_address + 1] = operand_not[8:]

    elif opcode == 12:  # SHL
        data = data[1:] + "0"
        registers[operand_hex][0] = data

    elif opcode == 13:  # SHR
        data = "0" + data[:-1]
        registers[operand_hex][0] = data

    elif opcode == 15:  # PUSH
        memory[S] = data[:8]
        S -= 1
        memory[S] = data[8:]
        S -= 1

    elif opcode == 16:  # POP
        registers[operand_hex][0] = memory[S+2] + memory[S+1]
        S += 2

    elif opcode == 17:  # CMP
        operand = not_numb(data)
        operand = addition(operand, bin_one)
        addition(A[0],operand)
    elif opcode == 18: # JMP
        PC = int(data,2)-1
    elif opcode == 19: # JZ JE
        if ZF:
            PC = int(data,2)-1
    elif opcode == 20: # JNZ JNE
        if not(ZF):
            PC = int(data,2)-1
    elif opcode == 21: # JC
        if CF == 1:
            PC = int(data,2)-1
    elif opcode == 22: # JNC
        if CF == 0:
            PC = int(data,2)-1
    elif opcode == 23: # JA
        if not(SF) and not(ZF):
            PC = int(data,2)-1
    elif opcode == 24: # JAE
        if not(SF):
            PC = int(data,2)-1
    elif opcode == 25: # JB
        if SF:
            PC = int(data,2)-1
    elif opcode == 26: # JBE
        if SF or ZF:
            PC = int(data,2)-1
    elif opcode == 27: # READ
        inputs = input()
        inputs = inputs[0]
        inputs = (str(bin(ord(inputs)))[2:]).zfill(16) # changing char to bin to string to remove 0b from beginning and completing to 16 bits
        if addrMode == 1:
            registers[operand_hex][0] = inputs
        elif addrMode == 2:
            memo_address = registers[operand_hex][0]
            memo_address = int(memo_address,2)
            memory[memo_address] = inputs[:8]
            memory[memo_address+1] = inputs[8:]
        elif addrMode == 3:
            memo_address = int(operand,2)
            memory[memo_address] = inputs[:8]
            memory[memo_address+1] = inputs[8:]
    elif opcode == 28: # PRINT
        outputFile.write(chr(int(data,2))+"\n")
    PC += 1

outputFile.close()


import copy
import json

from ..exceptions import (
    CollectionNotExistException,
    PartitionNotExistException,
    ExceptionsMessage,
)

from .prepare import Prepare
from .search import SearchResult
from .mutation import MutationResult
from .future import SearchFuture, MutationFuture
from ..client.types import Replica

class Partition:
    def __init__(self, collection, name, description="", **kwargs):
        # TODO: Need a place to store the description
        from .collection import Collection
        if not isinstance(collection, Collection):
            raise CollectionNotExistException(message=ExceptionsMessage.CollectionType)
        self._collection = collection
        self._name = name
        self._description = description
        self._schema = collection._schema
        self._consistency_level = collection._consistency_level
        self._kwargs = kwargs

        conn = self._get_connection()
        if kwargs.get("construct_only", False):
            return
        copy_kwargs = copy.deepcopy(kwargs)
        if copy_kwargs.get("partition_name"):
            copy_kwargs.pop("partition_name")
        has = conn.has_partition(self._collection.name, self._name, **copy_kwargs)
        if not has:
            conn.create_partition(self._collection.name, self._name, **copy_kwargs)

        self._schema_dict = self._schema.to_dict()
        self._schema_dict["consistency_level"] = self._consistency_level

    def __repr__(self):
        return json.dumps({
            'name': self.name,
            'collection_name': self._collection.name,
            'description': self.description,
        })

    def _get_connection(self):
        return self._collection._get_connection()

    @property
    def description(self) -> str:
        """ Return the description text.

        :return:  Partition description
        :rtype: str

        :example:
            >>> from pymilvus import connections, Collection, Partition, FieldSchema, CollectionSchema, DataType
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_partition_description", schema)
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> partition.description
            'comedy films'
        """
        return self._description

    @property
    def name(self) -> str:
        """
        Return the partition name.

        :return str: Partition name, return when operation is successful
        :example:
            >>> from pymilvus import connections, Collection, Partition, FieldSchema, CollectionSchema, DataType
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_partition_name", schema)
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> partition.name
            'comedy'
        """
        return self._name

    @property
    def is_empty(self) -> bool:
        """
        Returns whether the partition is empty

        :return bool: Whether the partition is empty
        * True: The partition is empty.
        * False: The partition is not empty.

        :example:

            >>> from pymilvus import connections, Collection, Partition, FieldSchema, CollectionSchema, DataType
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_partition_is_empty", schema)
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> partition.is_empty
            True
        """
        return self.num_entities == 0

    @property
    def num_entities(self, **kwargs) -> int:
        """
        Return the number of entities.

        :return int: Number of entities in this partition.

        :example:
            >>> from pymilvus import connections, Collection, Partition, FieldSchema, CollectionSchema, DataType
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_partition_num_entities", schema)
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> data = [
            ...     [i for i in range(10)],
            ...     [[float(i) for i in range(2)] for _ in range(10)],
            ... ]
            >>> partition.insert(data)
            >>> partition.num_entities
            10
        """
        conn = self._get_connection()
        stats = conn.get_partition_stats(collection_name=self._collection.name, partition_name=self._name, **kwargs)
        result = {stat.key: stat.value for stat in stats}
        result["row_count"] = int(result["row_count"])
        return result["row_count"]

    def flush(self, timeout=None, **kwargs):
        """ Flush """
        conn = self._get_connection()
        conn.flush([self._collection.name], timeout=timeout, **kwargs)

    def drop(self, timeout=None, **kwargs):
        """
        Drop the partition, as well as its corresponding index files.

        :param timeout: An optional duration of time in seconds to allow for the RPC. When timeout
                        is set to None, client waits until server response or error occur
        :type  timeout: float

        :raises PartitionNotExistException:
            When partitoin does not exist

        :example:
            >>> from pymilvus import connections, Collection, Partition, FieldSchema, CollectionSchema, DataType
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_partition_drop", schema)
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> partition.drop()
        """
        conn = self._get_connection()
        if conn.has_partition(self._collection.name, self._name, timeout=timeout, **kwargs) is False:
            raise PartitionNotExistException(message=ExceptionsMessage.PartitionNotExist)
        return conn.drop_partition(self._collection.name, self._name, timeout=timeout, **kwargs)

    def load(self, replica_number=1, timeout=None, **kwargs):
        """
        Load the partition from disk to memory.

        :param replica_number: The replication numbers to load.
        :type  replica_number: int

        :param timeout: An optional duration of time in seconds to allow for the RPC. When timeout
                        is set to None, client waits until server response or error occur
        :type  timeout: float

        :raises ParamError:
            If params are invalid

        :example:
            >>> from pymilvus import connections, Collection, Partition, FieldSchema, CollectionSchema, DataType
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_partition_load", schema)
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> partition.load()
        """
        # TODO(yukun): If field_names is not None and not equal schema.field_names,
        #  raise Exception Not Supported,
        #  if index_names is not None, raise Exception Not Supported
        conn = self._get_connection()
        if conn.has_partition(self._collection.name, self._name, **kwargs):
            return conn.load_partitions(self._collection.name, [self._name], replica_number, timeout=timeout, **kwargs)
        raise PartitionNotExistException(message=ExceptionsMessage.PartitionNotExist)

    def release(self, timeout=None, **kwargs):
        """
        Release the partition from memory.

        :param timeout: An optional duration of time in seconds to allow for the RPC. When timeout
                        is set to None, client waits until server response or error occur
        :type  timeout: float

        :raises PartitionNotExistException:
            When partitoin does not exist

        :example:
            >>> from pymilvus import connections, Collection, Partition, FieldSchema, CollectionSchema, DataType
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_partition_release", schema)
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> partition.load()
            >>> partition.release()
        """
        conn = self._get_connection()
        if conn.has_partition(self._collection.name, self._name, **kwargs):
            return conn.release_partitions(self._collection.name, [self._name], timeout=timeout, **kwargs)
        raise PartitionNotExistException(message=ExceptionsMessage.PartitionNotExist)

    def insert(self, data, timeout=None, **kwargs):
        """
        Insert data into partition.

        :param data: The specified data to insert, the dimension of data needs to align with column
                     number
        :type  data: list-like(list, tuple) object or pandas.DataFrame

        :param timeout: An optional duration of time in seconds to allow for the RPC. When timeout
                        is set to None, client waits until server response or error occur
        :type  timeout: float

        :param kwargs:
            * *timeout* (``float``) --
              An optional duration of time in seconds to allow for the RPC. When timeout
              is set to None, client waits until server response or error occur.

        :return: A MutationResult object contains a property named `insert_count` represents how many
        entities have been inserted into milvus and a property named `primary_keys` is a list of primary
        keys of the inserted entities.
        :rtype: MutationResult

        :raises PartitionNotExistException:
            When partitoin does not exist

        :example:
            >>> from pymilvus import connections, Collection, Partition, FieldSchema, CollectionSchema, DataType
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_partition_insert", schema)
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> data = [
            ...     [i for i in range(10)],
            ...     [[float(i) for i in range(2)] for _ in range(10)],
            ... ]
            >>> partition.insert(data)
            >>> partition.num_entities
            10
        """
        conn = self._get_connection()
        if conn.has_partition(self._collection.name, self._name, **kwargs) is False:
            raise PartitionNotExistException(message=ExceptionsMessage.PartitionNotExist)
        # TODO: check insert data schema here?
        entities = Prepare.prepare_insert_data(data, self._collection.schema)
        res = conn.batch_insert(self._collection.name, entities=entities, partition_name=self._name,
            timeout=timeout, orm=True, schema=self._schema_dict, **kwargs)
        if kwargs.get("_async", False):
            return MutationFuture(res)
        return MutationResult(res)

    def delete(self, expr, timeout=None, **kwargs):
        """ Delete entities with an expression condition.

        :param expr: The expression to specify entities to be deleted
        :type  expr: str

        :param timeout: An optional duration of time in seconds to allow for the RPC. When timeout
                        is set to None, client waits until server response or error occur
        :type  timeout: float

        :return: A MutationResult object contains a property named `delete_count` represents how many
                 entities will be deleted.
        :rtype: MutationResult

        :raises RpcError: If gRPC encounter an error
        :raises ParamError: If parameters are invalid
        :raises BaseException: If the return result from server is not ok

        :example:
            >>> from pymilvus import connections, Collection, Partition, FieldSchema, CollectionSchema, DataType
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> test_collection = Collection("test_partition_delete", schema)
            >>> test_partition = test_collection.create_partition("comedy", "comedy films")
            >>> data = [
            ...     [i for i in range(10)],
            ...     [[float(i) for i in range(2)] for _ in range(10)],
            ... ]
            >>> test_partition.insert(data)
            (insert count: 10, delete count: 0, upsert count: 0, timestamp: 431044482906718212)
            >>> test_partition.num_entities
            10
            >>> test_partition.delete("film_id in [0, 1]")
            (insert count: 0, delete count: 2, upsert count: 0, timestamp: 431044582560759811)
        """

        conn = self._get_connection()
        res = conn.delete(self._collection.name, expr, self.name, timeout=timeout, **kwargs)
        if kwargs.get("_async", False):
            return MutationFuture(res)
        return MutationResult(res)

    def search(self, data, anns_field, param, limit,
               expr=None, output_fields=None, timeout=None, round_decimal=-1, **kwargs):
        """ Conducts a vector similarity search with an optional boolean expression as filter.

        Args:
            data (``List[List[float]]``): The vectors of search data.
                the length of data is number of query (nq), and the dim of every vector in data must be equal to
                the vector field's of collection.
            anns_field (``str``): The name of the vector field used to search of collection.
            param (``dict[str, Any]``):

                The parameters of search. The followings are valid keys of param.

                * *nprobe*, *ef*, *search_k*, etc
                    Corresponding search params for a certain index.

                * *metric_type* (``str``)
                    similar metricy types, the value must be of type str.

                * *offset* (``int``, optional)
                    offset for pagination.

                * *limit* (``int``, optional)
                    limit for the search results and pagination.

                example for param::

                    {
                        "nprobe": 128,
                        "metric_type": "L2",
                        "offset": 10,
                        "limit": 10,
                    }

            limit (``int``): The max number of returned record, also known as `topk`.
            expr (``str``): The boolean expression used to filter attribute. Default to None.

                example for expr::

                    "id_field >= 0", "id_field in [1, 2, 3, 4]"

            output_fields (``List[str]``, optional):
                The name of fields to return in the search result.  Can only get scalar fields.
            round_decimal (``int``, optional): The specified number of decimal places of returned distance
                Defaults to -1 means no round to returned distance.
            **kwargs (``dict``): Optional search params

                *  *_async* (``bool``, optional)
                    Indicate if invoke asynchronously.
                    Returns a SearchFuture if True, else returns results from server directly.

                * *_callback* (``function``, optional)
                    The callback function which is invoked after server response successfully.
                    It functions only if _async is set to True.

                * *consistency_level* (``str/int``, optional)
                    Which consistency level to use when searching in the collection.

                    Options of consistency level: Strong, Bounded, Eventually, Session, Customized.

                    Note: this parameter will overwrite the same parameter specified when user created the collection,
                    if no consistency level was specified, search will use the consistency level when you create the
                    collection.

                * *guarantee_timestamp* (``int``, optional)
                    Instructs Milvus to see all operations performed before this timestamp.
                    By default Milvus will search all operations performed to date.

                    Note: only valid in Customized consistency level.

                * *graceful_time* (``int``, optional)
                    Search will use the (current_timestamp - the graceful_time) as the
                    `guarantee_timestamp`. By default with 5s.

                    Note: only valid in Bounded consistency level

                * *travel_timestamp* (``int``, optional)
                    A specific timestamp to get results based on a data view at.

        Returns:
            SearchResult:
                Returns ``SearchResult`` if `_async` is False , otherwise ``SearchFuture``

        .. _Metric type documentations:
            https://milvus.io/docs/v2.2.x/metric.md
        .. _Index documentations:
            https://milvus.io/docs/v2.2.x/index.md
        .. _How guarantee ts works:
            https://github.com/milvus-io/milvus/blob/master/docs/developer_guides/how-guarantee-ts-works.md

        Raises:
            MilvusException: If anything goes wrong

        :example:
            >>> from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
            >>> import random
            >>> connections.connect()
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_collection_search", schema)
            >>> collection.create_index("films", {"index_type": "FLAT", "metric_type": "L2", "params": {}})
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> # insert
            >>> data = [
            ...     [i for i in range(10)],
            ...     [[random.random() for _ in range(2)] for _ in range(10)],
            ... ]
            >>> partition.insert(data)
            >>> partition.load()
            >>> # search
            >>> search_param = {
            ...     "data": [[1.0, 1.0]],
            ...     "anns_field": "films",
            ...     "param": {"metric_type": "L2"},
            ...     "limit": 2,
            ...     "expr": "film_id > 0",
            ... }
            >>> res = partition.search(**search_param)
            >>> assert len(res) == 1
            >>> hits = res[0]
            >>> assert len(hits) == 2
            >>> print(f"- Total hits: {len(hits)}, hits ids: {hits.ids} ")
            - Total hits: 2, hits ids: [8, 5]
            >>> print(f"- Top1 hit id: {hits[0].id}, distance: {hits[0].distance}, score: {hits[0].score} ")
            - Top1 hit id: 8, distance: 0.10143111646175385, score: 0.10143111646175385
        """
        conn = self._get_connection()
        res = conn.search(self._collection.name, data, anns_field, param, limit, expr, [self._name], output_fields,
                          round_decimal=round_decimal, timeout=timeout, schema=self._schema_dict, **kwargs)
        if kwargs.get("_async", False):
            return SearchFuture(res)
        return SearchResult(res)

    def query(self, expr, output_fields=None, timeout=None, **kwargs):
        """
        Query with a set of criteria, and results in a list of records that match the query exactly.

        :param expr: The query expression
        :type  expr: str

        :param output_fields: A list of fields to return
        :type  output_fields: list[str]

        :param timeout: An optional duration of time in seconds to allow for the RPC. When timeout
                        is set to None, client waits until server response or error occur
        :type  timeout: float

        :param kwargs:
            * *consistency_level* (``str/int``) --
              Which consistency level to use during a query on the collection. For details, see
              https://github.com/milvus-io/milvus/blob/master/docs/developer_guides/how-guarantee-ts-works.md.
              Note: this parameter will overwrite the same parameter specified when user created the collection,
              if no consistency level was specified, query will use the collection consistency level.
            * *guarantee_timestamp* (``int``) --
              This function instructs Milvus to see all operations performed before a provided timestamp. If no
              such timestamp is specified, Milvus will query all operations performed to date.
              Note: only used in Customized consistency level.
            * *graceful_time* (``int``) --
              Only used in bounded consistency level. If graceful_time is set, PyMilvus will use current timestamp minus
              the graceful_time as the `guarantee_timestamp`. This option is 5s by default if not set.
            * *travel_timestamp* (``int``) --
              Users can specify a timestamp in a search to get results based on a data view
              at a specified point in time.

        :return: A list that contains all results
        :rtype: list

        :raises RpcError: If gRPC encounter an error
        :raises ParamError: If parameters are invalid
        :raises BaseException: If the return result from server is not ok

        :example:
            >>> from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
            >>> import random
            >>> connections.connect()
            <pymilvus.client.stub.Milvus object at 0x7f8579002dc0>
            >>> schema = CollectionSchema([
            ...     FieldSchema("film_id", DataType.INT64, is_primary=True),
            ...     FieldSchema("film_date", DataType.INT64),
            ...     FieldSchema("films", dtype=DataType.FLOAT_VECTOR, dim=2)
            ... ])
            >>> collection = Collection("test_collection_query", schema)
            >>> partition = Partition(collection, "comedy", "comedy films")
            >>> # insert
            >>> data = [
            ...     [i for i in range(10)],
            ...     [i + 2000 for i in range(10)],
            ...     [[random.random() for _ in range(2)] for _ in range(10)],
            ... ]
            >>> partition.insert(data)
            >>> partition.num_entities
            10
            >>> partition.load()
            >>> # query
            >>> expr = "film_id in [ 0, 1 ]"
            >>> res = partition.query(expr, output_fields=["film_date"])
            >>> assert len(res) == 2
            >>> print(f"- Query results: {res}")
            - Query results: [{'film_id': 0, 'film_date': 2000}, {'film_id': 1, 'film_date': 2001}]
        """
        conn = self._get_connection()
        res = conn.query(self._collection.name, expr, output_fields, [self._name],
                         timeout=timeout, schema=self._schema_dict, **kwargs)
        return res

    def get_replicas(self, timeout=None, **kwargs) -> Replica:
        """get_replicas returns the current collection's replica information

        :param timeout: An optional duration of time in seconds to allow for the RPC. When timeout
                        is set to None, client waits until server response or error occur
        :type  timeout: float

        :raises BaseException: If the collection does not exist.

        :example:
        """
        conn = self._get_connection()
        return conn.get_replicas(self._collection.name, timeout=timeout, **kwargs)


def identify_link_type(link):
    """A function to identify the type of links returns 1 if its post or 2 if it's profile link"""
    slink = link.split('/')
    if 'p' in slink or 'tv' in slink or 'reel' in slink:
        return 1
    else:
        return 2

def extract_username(link):
    """Extract usernames from the link only for profile links"""
    slink = link.split('/')

    for counter, i in enumerate(slink):
        if 'instagram' in i:
            if 'igshid' in slink[counter + 1]:
                return slink[counter + 1].split('?')[0]
            else:
                return slink[counter + 1]

def extract_post_link(link):
    """Extract the link of post"""

    slink = link.split('/')
    url = 'https://www.instagram.com/'

    if 'p' in slink:
        url += 'p/' + slink[slink.index('p') + 1][:12]
        return url

    if 'tv' in slink:
        url += 'tv/' + slink[slink.index('tv') + 1][:12]
        return url

    if 'reel' in slink:
        url += 'reel/' + slink[slink.index('reel') + 1][:12]
        return url


# pounds = int(input())
#
# dollars = pounds*1.31
# print(f"{dollars:.3f}")

from forex_python.converter import CurrencyRates

pounds = int(input("Amount in GBP: "))
c = CurrencyRates()
currency_rate = c.get_rate("BGP", "USD")
dollars = pounds * currency_rate

print(f"{dollars:.3f}")

3. Data Types and Variables - Lab/3.5. Pounds to Dollars.py


import os
import re
import colorama as color

class Tile:
    DIRECTORIES = ["earth nav data", "terrain", "textures"]

    lat = None
    long = None
    tile_dir = None
    tile_name = None
    water_only = False
    opts = {}

    def __init__(self, tile, dir, **opts):
        self.tile_name = tile
        self.tile_dir = os.path.join(dir, self.tile_name)
        (self.lat, self.long) = re.findall("([+-]\d+)", self.tile_name.lstrip("zOrtho4XP_").strip())
        self.verbose = opts["verbose"] if "verbose" in opts else 0
        self.errors = list()
        self.textures = dict()

    def validate(self):
        for dir in self.DIRECTORIES:
            getattr(self, "validate_{}".format(re.sub("\s+", "_", dir)))()

        return self.errors

    def validate_dir(self, dir):
        path = os.path.join(self.tile_dir, dir)

        if self.verbose > 2: print("  Validating {:.<35} ".format(dir.upper() + " directory"), end="")

        if not os.path.isdir(path):
            if dir != "terrain":
                if self.verbose > 2: print(color.Fore.RED + "NOT FOUND")
                self.errors.append("Directory \"{}\" NOT FOUND".format(dir))

            return False

        if not os.listdir(path):
            if self.verbose > 2: print(color.Fore.RED + "IS EMPTY")
            self.errors.append("Directory \"{}\" IS EMPTY".format(dir))
            return False

        if self.verbose > 2: print(color.Fore.GREEN + "OKAY")

        return True

    def validate_earth_nav_data(self):
        if not self.validate_dir("earth nav data"):
            return False

        return True

    def validate_terrain(self):
        no_errors_found = True
        path = os.path.join(self.tile_dir, "terrain")

        self.textures = dict(terrain_check=True)

        # May not exist (e.g. Water only tile)
        # if os.path.isdir(path):
        if not self.validate_dir("terrain"):
            self.water_only = True
            if self.verbose > 2: print(color.Fore.YELLOW + "Water Only? (if Textures are okay, this is safe to ignore)")
            return True

        if self.verbose > 2:
            print("  Validating {:.<35} ".format("TERRAIN DATA"), end=(os.linesep if self.verbose > 3 else ""))

        for terrain_file in sorted(os.listdir(path)):

            if self.verbose > 3: print("    Checking {:.<35} ".format(terrain_file), end="")

            with open(os.path.join(path, terrain_file)) as tf:
                texture_data = tf.read()

            try:
                texture_file = os.path.basename(re.search("../textures/(.+\.dds)", texture_data)[0])
                texture_path = os.path.join(self.tile_dir, "textures", texture_file)

                if not os.path.exists(texture_path):
                    no_errors_found = False
                    if self.verbose > 3: print(color.Fore.RED + "NO REFERENCE IN TEXTURES")
                    if texture_file not in self.textures:
                        self.errors.append("Terrain points to {}, which does not exist".format(texture_file))
                else:
                    if self.verbose > 3: print(color.Fore.GREEN + "OKAY")

                self.textures[texture_file] = None
            except TypeError:
                no_errors_found = False
                if self.verbose > 3: print(color.Fore.RED + "NO TEXTURES FOUND")
                self.errors.append("Terrain {} does not reference any Textures".format(terrain_file))

        if 2 < self.verbose <= 3:
            if no_errors_found:
                print(color.Fore.GREEN + "OKAY")
            else:
                print(color.Fore.RED + "ERROR")

        return no_errors_found

    def validate_textures(self):
        texture_count = 0
        no_errors_found = True
        path = os.path.join(self.tile_dir, "textures")

        if not self.validate_dir("textures"): return False

        if "terrain_check" not in self.textures: raise RuntimeError("Textures called before Terrains")

        if self.verbose > 2:
            print("  Validating {:.<35} ".format("TEXTURES DATA"), end=(os.linesep if self.verbose > 3 else ""))

        for texture_file in sorted(os.listdir(path)):
            if re.match(".*\.dds", texture_file) is None: continue

            texture_count += 1

            if self.verbose > 3: print("    Checking {:.<35} ".format(texture_file), end="")

            if texture_file not in self.textures:
                no_errors_found = False

                if self.verbose > 3: print(color.Fore.RED + "ERROR")

                if self.water_only:
                    if 2 < self.verbose <= 3:
                        print(color.Fore.RED + "ERROR")

                    self.errors.append("Textures were found, but no TERRAIN directory exists")
                    return False  # no need to check the remaining files
                else:
                    self.errors.append(
                        "Texture file {} exists, but was not referenced".format(texture_file))
            else:
                if self.verbose > 3: print(color.Fore.GREEN + "OKAY")

        if texture_count == 0 and self.verbose > 3:
            if self.water_only:
                print("    {:.<44} {}".format("Water Only Tile", color.Fore.GREEN + "OKAY"))
            else:
                print("    {:.<44} {}".format("NO TEXTURE DATA", color.Fore.RED + "ERROR"))

        if 2 < self.verbose <= 3:
            if no_errors_found:
                print(color.Fore.GREEN + "OKAY")
            else:
                print(color.Fore.RED + "ERROR")

        return no_errors_found


import sys
from os import getenv
from typing import Any, Dict, Union

from click import echo
from fideslib.core.config import load_file
from toml import dump, load

DEFAULT_CONFIG_PATH = ".fides/fides.toml"

def get_test_mode() -> bool:
    test_mode = getenv("FIDES__TEST_MODE", "").lower() == "true"
    return test_mode

def get_config_from_file(
    config_path_override: str,
    section: str,
    option: str,
) -> Union[str, bool, int, None]:
    """
    Return the value currently written to the config file for the specified `section.option`.
    """

    try:
        config_path = config_path_override or load_file(
            file_names=[DEFAULT_CONFIG_PATH]
        )
    except FileNotFoundError as error:
        raise error

    current_config = load(config_path)

    config_section = current_config.get(section)
    if config_section is not None:
        config_option = config_section.get(option)
        if config_option is not None:
            return config_option

    return None

def check_if_required_config_vars_are_configured() -> None:
    app_encryption_key: Union[str, int, None] = getenv(
        "FIDES__SECURITY__APP_ENCRYPTION_KEY"
    )
    oauth_root_client_id: Union[str, int, None] = getenv(
        "FIDES__SECURITY__OAUTH_ROOT_CLIENT_ID"
    )
    oauth_root_client_secret: Union[str, int, None] = getenv(
        "FIDES__SECURITY__OAUTH_ROOT_CLIENT_SECRET"
    )
    try:
        if not app_encryption_key:
            app_encryption_key = get_config_from_file(
                "", "security", "app_encryption_key"
            )
        if not oauth_root_client_id:
            oauth_root_client_id = get_config_from_file(
                "", "security", "oauth_root_client_id"
            )
        if not oauth_root_client_secret:
            oauth_root_client_secret = get_config_from_file(
                "", "security", "oauth_root_client_secret"
            )
    except FileNotFoundError:
        pass

    missing_required_config_vars = []
    if app_encryption_key is None:
        missing_required_config_vars.append(
            ("security.app_encryption_key", "FIDES__SECURITY__APP_ENCRYPTION_KEY")
        )
    if oauth_root_client_id is None:
        missing_required_config_vars.append(
            ("security.oauth_root_client_id", "FIDES__SECURITY__OAUTH_ROOT_CLIENT_ID")
        )
    if oauth_root_client_secret is None:
        missing_required_config_vars.append(
            (
                "security.oauth_root_client_secret",
                "FIDES__SECURITY__OAUTH_ROOT_CLIENT_SECRET",
            )
        )

    if len(missing_required_config_vars) > 0:
        print(
            "There are missing required config variables. Please add the following config variables to either the "
            "`fides.toml` file or your environment variables to start Fides: \n"
        )
        for missing_var in missing_required_config_vars:
            print(f"fides.toml: {missing_var[0]} or ENV VAR: {missing_var[1]}")

        print(
            "\nVisit the Fides deployment documentation for more information: "
            "https://ethyca.github.io/fides/deployment/"
        )
        sys.exit(1)

def update_config_file(  # type: ignore
    updates: Dict[str, Dict[str, Any]],
    config_path_override: str,
) -> None:
    """
    Overwrite the existing config file with a new version that includes the desired `updates`.

    :param updates: A nested `dict`, where top-level keys correspond to configuration sections and top-level values contain `dict`s whose key/value pairs correspond to the desired option/value updates.
    :param config_path: The path to the current configuration file.
    """

    try:
        config_path = config_path_override or load_file(
            file_names=[DEFAULT_CONFIG_PATH]
        )
    except FileNotFoundError as error:
        raise error

    current_config = load(config_path)

    for key, value in updates.items():
        if key in current_config:
            current_config[key].update(value)
        else:
            current_config.update({key: value})

    with open(config_path, "w", encoding="utf-8") as config_file:
        dump(current_config, config_file)

    echo(f"Updated {config_path}:")

    for key, value in updates.items():
        for subkey, val in value.items():
            echo(f"\tSet {key}.{subkey} = {val}")


# date: 04/30/18
# author: Hana Vrzakova
# description: Features derived from saccade velocities.

from __future__ import division
import numpy as np
import pandas as pd

class SaccadeVelocity:
    def __init__(self):
        self.Velocities = []

        self.Mean = []
        self.Median = []
        self.Max = []
        self.Min = []
        self.Sum = []

        self.Prior = []
        self.Last = []

        self.RatioPriorLast = []

    def countStatistics(self,  fixationDistance,  saccadeDuration,  prefix,  suffix):
        velocities = np.divide(fixationDistance ,  saccadeDuration)

        self.Velocities.append(velocities)

        self.Mean.append( np.sum(fixationDistance) / np.sum(saccadeDuration))
        self.Median.append( np.median(velocities) )
        #outSTD se pocita jinak?
        #outVar repete
        self.Max.append( np.max(velocities))
        self.Min.append( np.min(velocities)) # a na jake pozici - abs. hodnoty rikaji malo,
        self.Sum.append(np.sum(velocities))

        self.Prior.append(velocities[-2])
        self.Last.append( velocities[-1])

        ratio = -1
        if(velocities[-1] > 0):
            ratio = velocities[-2]/velocities[-1]
        self.RatioPriorLast.append(ratio)

    def countStatisticsPandas(self, distances, durations):
        velocities = distances/durations

        self.velocities = velocities

        distMean = velocities.mean()
        distMedian = velocities.median()
        distVariance = velocities.var()
        distSTD = velocities.std()
        distMin = velocities.min()
        distMax = velocities.max()
        distSum = velocities.sum()

        distFirst = velocities.iloc[0]
        distLast = velocities.iloc[-1]
        distPriorLast = velocities.iloc[-2]

        distRatioFirstLast = distFirst / distLast
        distRatioFirstPrior = distFirst / distPriorLast
        distRatioPriorLast = distPriorLast / distLast

        dfOutput = pd.DataFrame([distMean, distMedian, distVariance, distSTD,
                                 distMin, distMax, distSum,
                                 distFirst, distLast, distPriorLast,
                                 distRatioFirstLast, distRatioFirstPrior, distRatioPriorLast]).transpose()

        dfOutput.columns = ["saccVelMean", "saccVelMedian", "saccVelVariance", "saccVelSTD",
                            "saccVelMin", "saccVelMax", "saccVelSum",
                            "saccVelFirst", "saccVelLast", "saccVelPriorLast",
                            "saccVelRatioFirstLast", "saccVelRatioFirstPrior", "saccVelRatioPriorLast"]

        return dfOutput

    def allToString(self):
        self.strMean = np.array(self.Mean).astype('|S10')
        self.strMedian= np.array(self.Median).astype('|S10')
        #self.strStddev = np.array(self.Stddev).astype('|S10')
        #self.strVar = np.array(self.Var).astype('|S10')
        self.strMax = np.array(self.Max).astype('|S10')
        self.strMin = np.array(self.Min).astype('|S10')
        self.strSum = np.array(self.Sum).astype('|S10')

        self.strPrior = np.array(self.Prior).astype('|S10')
        self.strLast = np.array(self.Last).astype('|S10')

        self.strRatioPriorLast = np.array(self.RatioPriorLast).astype('|S10')


import os
from setuptools import setup, find_packages

setup_py_dir = os.path.dirname(os.path.realpath(__file__))
need_files = []

setup(
    name='robot-agents',
    version='0.0.1',
    author="Elena Rampone",
    author_email="elena.rampone@iit.it",
    description="Robot Agents: toolkit to develop and test RL algorithms on robotic manipulation tasks",
    python_requires='>=3.*',
    install_requires=['stable_baselines'],
)


import random
from enum import Enum, unique

@unique
class Factions(Enum):
    """
    Enum to represent factions. Numbers match up with faction identification
    ids from the game.
    """
    UEF = 1
    AEON = 2
    CYBRAN = 3
    SERAPHIM = 4

    # Shall remain the last element: not a real faction number.
    RANDOM = 5

    @staticmethod
    def get_random_faction():
        """
        :return: A random faction, but never RANDOM.
        """
        possibilities = list(Factions)
        possibilities.pop()
        return random.choice(possibilities)

    @staticmethod
    def set_faction(sub_factions=[]):
        if any(sub_factions):
            possibilities = []
            for faction, selected in zip(list(Factions)[:-1], sub_factions):
                if selected:
                    possibilities.append(faction)
        else:
            possibilities = list(Factions)[:-1]
        return random.choice(possibilities)

    @staticmethod
    def from_name(name):
        name = name.lower()
        if name == "uef":
            return Factions.UEF
        elif name == "aeon":
            return Factions.AEON
        elif name == "cybran":
            return Factions.CYBRAN
        elif name == "seraphim":
            return Factions.SERAPHIM
        elif name == "random":
            return Factions.RANDOM

        raise ValueError("Invalid faction name provided: {}".format(name))

    def to_name(self):
        if self == Factions.UEF:
            return "uef"
        elif self == Factions.AEON:
            return "aeon"
        elif self == Factions.CYBRAN:
            return "cybran"
        elif self == Factions.SERAPHIM:
            return "seraphim"
        elif self == Factions.RANDOM:
            return "random"

        raise ValueError("Invalid faction id provided: {}".format(self))