text:
#!/usr/bin/python3
import random
import math
import numpy as np

"""
Constants
"""
variance = 0.01

CHECKERBOARD_SIZE = 0.2

"""
Functions
"""

# def get_swiss_roll_dataset(numOfSamples):
#     sample_list = []
#     label_list = []
#     for x in range(0, numOfSamples):
#         # noise_test = random.random()
#         # if noise_test < 0.1:  # Add gaussian noise
#         #     noise_1 = numpy.random.normal(0, 0.1)
#         #     noise_2 = numpy.random.normal(0, 0.1)
#         #     noise_3 = numpy.random.normal(0, 0.1)
#         #     sample_list.append([noise_1, noise_2, noise_3])
#         #     continue
#         p_i = random.random()
#         q_i = random.random()
#         t_i = math.pi * 3 / 2 * (1 + 2 * p_i)
#
#         x_i = [np.random.normal(t_i * math.cos(t_i), variance),
#                np.random.normal(t_i * math.sin(t_i), variance),
#                np.random.normal(30 * q_i, variance),]
#         sample_list.append(x_i)
#         label_list.append(label)
#     return sample_list, label_list

def get_swiss_roll_dataset_with_labels2(n):
    t = (3 * math.pi / 2) * (1 + 2 * np.random.random(n))
    height = 30 * np.random.random(n)
    X = np.array([t * np.cos(t), height, t * np.sin(t)]) + variance * np.random.normal(0, 1, n * 3).reshape(3, n)
    labels = np.fmod(np.around(t / 2) + np.around(height / 12), 2)
    return X.T.tolist(), labels.reshape(n, 1).tolist()

# def get_broken_swiss_roll_dataset(numOfSamples):
#     sample_list = []
#     for x in range(0, numOfSamples):
#         # noise_test = random.random()
#         # if noise_test < 0.1:  # Add gaussian noise
#         #     noise_1 = numpy.random.normal(0, 0.1)
#         #     noise_2 = numpy.random.normal(0, 0.1)
#         #     noise_3 = numpy.random.normal(0, 0.1)
#         #     sample_list.append([noise_1, noise_2, noise_3])
#         #     continue
#         while True:
#             p_i = random.random()
#             q_i = random.random()
#             t_i = math.pi * 3 / 2 * (1 + 2 * p_i)
#             if p_i >= (4 / 5) or p_i <= (2 / 5):
#                 break
#
#         x_i = [np.random.normal(t_i * math.cos(t_i), variance),
#                np.random.normal(t_i * math.sin(t_i), variance),
#                np.random.normal(30 * q_i, variance)]
#         sample_list.append(x_i)
#     return sample_list

def get_broken_swiss_roll_dataset_with_label2(n):
    t1 = (3 * math.pi / 2) * (1 + 2 * np.random.random(math.floor(n / 2)) * 0.4)
    t2 = (3 * math.pi / 2) * (1 + 2 * (np.random.random(math.ceil(n / 2)) * 0.4 + 0.6))
    t = np.append(t1, t2)
    height = 30 * np.random.random(n)
    X = np.array([t * np.cos(t), height, t * np.sin(t)]) + variance * np.random.normal(0, 1, n * 3).reshape(3, n)
    labels = np.fmod(np.around(t / 2) + np.around(height / 12), 2)
    return X.T.tolist(), labels.reshape(n, 1).tolist()

# def get_helix_dataset(numOfSamples):
#     sample_list = []
#     result = dict()
#     for x in range(0, numOfSamples):
#         # noise_test = random.random()
#         # if noise_test < 0.1:  # Add gaussian noise
#         #     noise_1 = numpy.random.normal(0, 0.1)
#         #     noise_2 = numpy.random.normal(0, 0.1)
#         #     noise_3 = numpy.random.normal(0, 0.1)
#         #     sample_list.append([noise_1, noise_2, noise_3])
#         #     continue
#         p_i = random.random()
#
#         x_i = [np.random.normal((2 + math.cos(8 * p_i)) * math.cos(p_i), variance), np.random.normal((2 + math.cos(8 * p_i)) * math.sin(p_i), variance), np.random.normal(math.sin(8 * p_i), variance)]
#         sample_list.append(x_i)
#     return sample_list

def get_helix_dataset_with_label2(n):
    t = np.random.random(n) * 2 * math.pi;
    X = [(2 + np.cos(8 * t)) * np.cos(t), (2 + np.cos(8 * t)) * np.sin(t), np.sin(8 * t)] + variance * np.random.normal(0, 1, n * 3).reshape(3, n)
    labels = np.fmod(np.around(t * 1.5), 2);
    return X.T.tolist(), labels.reshape(n, 1).tolist()

# def get_twin_peaks(numOfSamples):
#     sample_list = []
#     for x in range(0, numOfSamples):
#         # noise_test = random.random()
#         # if noise_test < 0.1:  # Add gaussian noise
#         #     noise_1 = numpy.random.normal(0, 0.1)
#         #     noise_2 = numpy.random.normal(0, 0.1)
#         #     noise_3 = numpy.random.normal(0, 0.1)
#         #     sample_list.append([noise_1, noise_2, noise_3])
#         #     continue
#         p_i = random.random()
#         q_i = random.random()
#         x_i = [np.random.normal(1 - 2 * p_i, variance), np.random.normal(math.sin(math.pi - 2 * math.pi * p_i), variance), np.random.normal(math.tanh(3 - 6 * q_i), variance)]
#         sample_list.append(x_i)
#     return sample_list

# def get_twin_peaks_with_label(numOfSamples):
#     sample_list = []
#     label_list = []
#     for x in range(0, numOfSamples):
#         p_i = random.random()
#         q_i = random.random()
#
#         loc_p = int(p_i / CHECKERBOARD_SIZE) % 2
#         loc_q = int(q_i / CHECKERBOARD_SIZE) % 2
#         if (loc_p == loc_q):
#             label = 1
#         else:
#             label = -1
#
#         x_i = [np.random.normal(1 - 2 * p_i, variance),
#                np.random.normal(math.sin(math.pi - 2 * math.pi * p_i), variance),
#                np.random.normal(math.tanh(3 - 6 * q_i), variance)]
#         sample_list.append(x_i)
#         label_list.append(label)
#     return sample_list, label_list

def get_twin_peaks_with_label2(n):
    p = 1 - 2 * np.random.random(n)
    q = 1 - 2 * np.random.random(n)
    X = [p, q, np.sin(math.pi * p) * np.tanh(3 * q)] + variance * np.random.normal(0, 1, n * 3).reshape(3, n)
    X[2] *= 10
    labels = np.abs(np.fmod(np.sum(np.around((X.T + np.tile(np.amin(X, 1), (n, 1))) / 10), 1), 2))
    return X.T, labels.reshape(n, 1)

def get_hd_dataset(numOfSamples):
    sample_list = []
    coef = []
    for x in range(0, 5):
        one_set_coef = []
        for y in range(0, 5):
            one_set_coef.append(random.random())
        coef.append(one_set_coef)
    for x in range(0, numOfSamples):
        d_1 = random.random()
        d_2 = random.random()
        d_3 = random.random()
        d_4 = random.random()
        d_5 = random.random()
        powers = []
        for y in range(0, 5):
            one_set_pow = [pow(d_1, random.random()), pow(d_2, random.random()), pow(d_3, random.random()), pow(d_4, random.random()), pow(d_5, random.random())]
            powers.append(one_set_pow)

        x_i = (np.mat(coef + powers) * np.mat([[d_1], [d_2], [d_3], [d_4], [d_5]])).transpose()
        x_i = x_i.tolist()
        sample_list.append(x_i[0])
    return sample_list
    labels = np.fmod(np.sum(np.around((X.T + np.tile(np.amin(X, 1), (n, 1))) * 10), 1), 2)
    return X.T.tolist(), labels.reshape(n, 1).tolist()

# def get_hd_dataset(numOfSamples):
#     sample_list = []
#     coef = []
#     for x in range(0, 5):
#         one_set_coef = []
#         for y in range(0, 5):
#             one_set_coef.append(random.random())
#         coef.append(one_set_coef)
#     for x in range(0, numOfSamples):
#         d_1 = random.random()
#         d_2 = random.random()
#         d_3 = random.random()
#         d_4 = random.random()
#         d_5 = random.random()
#         powers = []
#         for y in range(0, 5):
#             one_set_pow = [pow(d_1, random.random()), pow(d_2, random.random()), pow(d_3, random.random()), pow(d_4, random.random()), pow(d_5, random.random())]
#             powers.append(one_set_pow)
#
#         x_i = (np.mat(coef + powers) * np.mat([[d_1], [d_2], [d_3], [d_4], [d_5]])).transpose()
#         x_i = x_i.tolist()
#         sample_list.append(x_i[0])
#     return sample_list

def get_hd_dataset_with_label2(n):
    x1 = np.random.random(n)
    x2 = np.random.random(n)
    x3 = np.random.random(n)
    x4 = np.random.random(n)
    x5 = np.random.random(n)
    X = [np.cos(x1), np.tanh(3 * x2), x1 + x3, x4 * np.sin(x2), np.sin(x1 + x5), x5 * np.cos(x2), x5 + x4, x2, x3 * x4, x1]
    X += variance * np.random.normal(0, 1, n * 10).reshape(10, n)
    labels = np.fmod(np.around(x1) + np.around(x2) + np.around(x3) + np.around(x4) + np.around(x5) + 1, 2)
    return X.T.tolist(), labels.reshape(n, 1).tolist()

# def get_hd_dataset_with_label2_2(n):
#     seed = np.random.random(math.ceil(math.pow(n, 1/5)))
#     A = np.array([p for p in itertools.product(seed, repeat = 5)][0:n]).T
#     X = [np.cos(A[0]), np.tanh(3 * A[1]), A[0] + A[2], A[3] * np.sin(A[1]), np.sin(A[0] + A[4]), A[4] * np.cos(A[1]), A[4] + A[3], A[1], A[2] * A[3], A[0]]
#     X += variance * np.random.normal(0, 1, n * 10).reshape(10, n)
#     labels = np.fmod(np.sum(np.around(A) + 1, 0), 2)
#     return X.T.tolist(), labels.reshape(n, 1).tolist()


text:
import numpy as np

from PuzzleLib.Backend import gpuarray
from PuzzleLib.Datasets import MnistLoader

from PuzzleLib.Containers import *
from PuzzleLib.Modules import *
from PuzzleLib.Handlers import *
from PuzzleLib.Optimizers import MomentumSGD
from PuzzleLib.Cost import CrossEntropy

from PuzzleLib.Converter.TensorRT.Tests.Common import benchModels
from PuzzleLib.Converter.TensorRT.BuildRTEngine import buildRTEngine, RTDataType
from PuzzleLib.Converter.TensorRT.DataCalibrator import DataCalibrator

def buildNet():
	seq = Sequential(name="lenet-5-like")
	seq.append(Conv2D(1, 16, 3))
	seq.append(MaxPool2D())
	seq.append(Activation(relu))

	seq.append(Conv2D(16, 32, 4))
	seq.append(MaxPool2D())
	seq.append(Activation(relu))

	seq.append(Flatten())
	seq.append(Linear(32 * 5 * 5, 1024))
	seq.append(Activation(relu))

	seq.append(Linear(1024, 10))

	return seq

def trainNet(net, data, labels, epochs):
	optimizer = MomentumSGD()
	optimizer.setupOn(net, useGlobalState=True)
	optimizer.learnRate = 0.1
	optimizer.momRate = 0.9

	cost = CrossEntropy(maxlabels=10)
	trainer = Trainer(net, cost, optimizer)
	validator = Validator(net, cost)

	for i in range(epochs):
		trainer.trainFromHost(
			data[:60000], labels[:60000], macroBatchSize=60000,
			onMacroBatchFinish=lambda train: print("Train error: %s" % train.cost.getMeanError())
		)
		print("Accuracy: %s" % (1.0 - validator.validateFromHost(data[60000:], labels[60000:], macroBatchSize=10000)))

		optimizer.learnRate *= 0.9

def validate(net, data, labels, batchsize=1):
	cost = CrossEntropy(maxlabels=10)
	validator = Validator(net, cost, batchsize=batchsize)

	return 1.0 - validator.validateFromHost(data[60000:], labels[60000:], macroBatchSize=10000)

def main():
	mnist = MnistLoader()
	data, labels = mnist.load(path="../TestData/")
	data, labels = data[:], labels[:]
	print("Loaded mnist")

	np.random.seed(1234)

	net = buildNet()
	trainNet(net, data, labels, 15)

	calibrator = DataCalibrator(data[:60000], cachename="../TestData/mnist_calibration_cache.bin")
	net.evalMode()

	engine = buildRTEngine(
		net, inshape=data[:1].shape, savepath="../TestData", dtype=RTDataType.int8, calibrator=calibrator
	)

	benchModels(net, engine, gpuarray.to_gpu(data[:1]))

	print("Net    accuracy: %s" % validate(net, data, labels))
	print("Engine accuracy: %s" % validate(engine, data, labels, batchsize=1))

if __name__ == "__main__":
	main()

ext: py

max_stars_repo_name: EmilPi/PuzzleLib

max_issues_repo_name: EmilPi/PuzzleLib

max_forks_repo_name: EmilPi/PuzzleLib

reason: import numpy


text:
import numpy as np

from .util import diagonal_dot, unitize, is_shape
from .points import point_plane_distance
from .constants import tol

def cross(triangles):
    '''
    Returns the cross product of two edges from input triangles

    triangles: vertices of triangles (n,3,3)
    returns:   cross product of two edge vectors (n,3)
    '''
    vectors = np.diff(triangles, axis=1)
    crosses = np.cross(vectors[:, 0], vectors[:, 1])
    return crosses

def area(triangles, sum=True):
    '''
    Calculates the sum area of input triangles

    Arguments
    ----------
    triangles: vertices of triangles (n,3,3)
    sum:       bool, return summed area or individual triangle area

    Returns
    ----------
    area:
        if sum: float, sum area of triangles
        else:   (n,) float, individual area of triangles
    '''
    crosses = cross(triangles)
    area = (np.sum(crosses ** 2, axis=1) ** .5) * .5
    if sum:
        return np.sum(area)
    return area

def normals(triangles):
    '''
    Calculates the normals of input triangles

    triangles: vertices of triangles, (n,3,3)
    returns:   normal vectors, (n,3)
    '''
    crosses = cross(triangles)
    normals, valid = unitize(crosses, check_valid=True)
    return normals, valid

def all_coplanar(triangles):
    '''
    Given a list of triangles, return True if they are all coplanar, and False if not.

    triangles: vertices of triangles, (n,3,3)
    returns:   all_coplanar, bool
    '''
    test_normal = normals(triangles)[0]
    test_vertex = triangles[0][0]
    distances = point_plane_distance(points=triangles[1:].reshape((-1, 3)),
                                     plane_normal=test_normal,
                                     plane_origin=test_vertex)
    all_coplanar = np.all(np.abs(distances) < tol.zero)
    return all_coplanar

def any_coplanar(triangles):
    '''
    Given a list of triangles, if the FIRST triangle is coplanar with ANY
    of the following triangles, return True.
    Otherwise, return False.
    '''
    test_normal = normals(triangles)[0]
    test_vertex = triangles[0][0]
    distances = point_plane_distance(points=triangles[1:].reshape((-1, 3)),
                                     plane_normal=test_normal,
                                     plane_origin=test_vertex)
    any_coplanar = np.any(np.all(np.abs(distances.reshape((-1, 3)) < tol.zero), axis=1))
    return any_coplanar

def mass_properties(triangles, density=1.0, skip_inertia=False):
    '''
    Calculate the mass properties of a group of triangles.

    Implemented from:
    http://www.geometrictools.com/Documentation/PolyhedralMassProperties.pdf
    '''
    crosses = cross(triangles)
    surface_area = np.sum(np.sum(crosses ** 2, axis=1) ** .5) * .5

    # these are the subexpressions of the integral
    f1 = triangles.sum(axis=1)

    # triangles[:,0,:] will give rows like [[x0, y0, z0], ...] (the first vertex of every triangle)
    # triangles[:,:,0] will give rows like [[x0, x1, x2], ...] (the x coordinates of every triangle)
    f2 = (triangles[:, 0, :] ** 2 +
          triangles[:, 1, :] ** 2 +
          triangles[:, 0, :] * triangles[:, 1, :] +
          triangles[:, 2, :] * f1)

    f3 = ((triangles[:, 0, :] ** 3) +
          (triangles[:, 0, :] ** 2) * (triangles[:, 1, :]) +
          (triangles[:, 0, :]) * (triangles[:, 1, :] ** 2) +
          (triangles[:, 1, :] ** 3) +
          (triangles[:, 2, :] * f2))

    g0 = (f2 + (triangles[:, 0, :] + f1) * triangles[:, 0, :])
    g1 = (f2 + (triangles[:, 1, :] + f1) * triangles[:, 1, :])
    g2 = (f2 + (triangles[:, 2, :] + f1) * triangles[:, 2, :])

    integral = np.zeros((10, len(f1)))
    integral[0] = crosses[:, 0] * f1[:, 0]
    integral[1:4] = (crosses * f2).T
    integral[4:7] = (crosses * f3).T

    for i in range(3):
        triangle_i = np.mod(i + 1, 3)
        integral[i + 7] = crosses[:, i] * ((triangles[:, 0, triangle_i] * g0[:, i]) +
                                           (triangles[:, 1, triangle_i] * g1[:, i]) +
                                           (triangles[:, 2, triangle_i] * g2[:, i]))

    coefficents = 1.0 / np.array([6, 24, 24, 24, 60, 60, 60, 120, 120, 120])
    integrated = integral.sum(axis=1) * coefficents

    volume = integrated[0]
    center_mass = integrated[1:4] / volume

    result = {'density': density,
              'surface_area': surface_area,
              'volume': volume,
              'mass': density * volume,
              'center_mass': center_mass.tolist()}

    if skip_inertia:
        return result

    inertia = np.zeros((3, 3))
    inertia[0, 0] = integrated[5] + integrated[6] - (volume * (center_mass[[1, 2]] ** 2).sum())
    inertia[1, 1] = integrated[4] + integrated[6] - (volume * (center_mass[[0, 2]] ** 2).sum())
    inertia[2, 2] = integrated[4] + integrated[5] - (volume * (center_mass[[0, 1]] ** 2).sum())
    inertia[0, 1] = (integrated[7] - (volume * np.product(center_mass[[0, 1]])))
    inertia[1, 2] = (integrated[8] - (volume * np.product(center_mass[[1, 2]])))
    inertia[0, 2] = (integrated[9] - (volume * np.product(center_mass[[0, 2]])))
    inertia[2, 0] = inertia[0, 2]
    inertia[2, 1] = inertia[1, 2]
    inertia[1, 0] = inertia[0, 1]
    inertia *= density

    result['inertia'] = inertia.tolist()

    return result

def windings_aligned(triangles, normals_compare):
    '''
    Given a set of triangles and a set of normals determine if the two are aligned

    Arguments
    ----------
    triangles: (n,3,3) set of vertex locations
    normals_compare: (n,3) set of normals

    Returns
    ----------
    aligned: (n) bool list, are normals aligned with triangles
    '''

    calculated, valid = normals(triangles)
    difference = diagonal_dot(calculated, normals_compare[valid])
    result = np.zeros(len(triangles), dtype=np.bool)
    result[valid] = difference > 0.0
    return result

def bounds_tree(triangles):
    '''
    Given a set of triangles, create an r-tree for broad- phase
    collision detection

    Arguments
    ---------
    triangles: (n, 3, 3) list of vertices

    Returns
    ---------
    tree: Rtree object
    '''
    from rtree import index

    # the property object required to get a 3D r-tree index
    properties = index.Property()
    properties.dimension = 3
    # the (n,6) interleaved bounding box for every triangle
    tri_bounds = np.column_stack((triangles.min(axis=1), triangles.max(axis=1)))

    # stream loading wasn't getting proper index
    tree = index.Index(properties=properties)
    for i, bounds in enumerate(tri_bounds):
        tree.insert(i, bounds)
    return tree

def nondegenerate(triangles):
    '''
    Find all triangles which have nonzero area.
    Degenerate triangles are divided into two cases:
    1) Two of the three vertices are colocated
    2) All three vertices are unique but colinear

    Arguments
    ----------
    triangles: (n, 3, 3) float, set of triangles

    Returns
    ----------
    nondegenerate: (n,) bool array of triangles that have area
    '''
    a, valid_a = unitize(triangles[:, 1] - triangles[:, 0], check_valid=True)
    b, valid_b = unitize(triangles[:, 2] - triangles[:, 0], check_valid=True)

    diff = np.zeros((len(triangles), 3))
    diff[valid_a] = a
    diff[valid_b] -= b

    ok = (np.abs(diff) > tol.merge).any(axis=1)
    ok[np.logical_not(valid_a)] = False
    ok[np.logical_not(valid_b)] = False

    return ok

def closest_point(triangles, points):
    """
    Return the closest point on the surface of each triangle for a
    list of corresponding points.
    Implements the method from "Real Time Collision Detection" and
    use the same variable names as "ClosestPtPointTriangle" to avoid
    being any more confusing.
    Parameters
    ----------
    triangles : (n, 3, 3) float
      Triangle vertices in space
    points : (n, 3) float
      Points in space
    Returns
    ----------
    closest : (n, 3) float
      Point on each triangle closest to each point
    """

    # check input triangles and points
    triangles = np.asanyarray(triangles, dtype=np.float64)
    points = np.asanyarray(points, dtype=np.float64)
    if not util.is_shape(triangles, (-1, 3, 3)):
        raise ValueError('triangles shape incorrect')
    if not util.is_shape(points, (len(triangles), 3)):
        raise ValueError('need same number of triangles and points!')

    # store the location of the closest point
    result = np.zeros_like(points)
    # which points still need to be handled
    remain = np.ones(len(points), dtype=np.bool)

    # if we dot product this against a (n, 3)
    # it is equivalent but faster than array.sum(axis=1)
    ones = [1.0, 1.0, 1.0]

    # get the three points of each triangle
    # use the same notation as RTCD to avoid confusion
    a = triangles[:, 0, :]
    b = triangles[:, 1, :]
    c = triangles[:, 2, :]

    # check if P is in vertex region outside A
    ab = b - a
    ac = c - a
    ap = points - a
    # this is a faster equivalent of:
    # diagonal_dot(ab, ap)
    d1 = np.dot(ab * ap, ones)
    d2 = np.dot(ac * ap, ones)

    # is the point at A
    is_a = np.logical_and(d1 < tol.zero, d2 < tol.zero)
    if any(is_a):
        result[is_a] = a[is_a]
        remain[is_a] = False

    # check if P in vertex region outside B
    bp = points - b
    d3 = np.dot(ab * bp, ones)
    d4 = np.dot(ac * bp, ones)

    # do the logic check
    is_b = (d3 > -tol.zero) & (d4 <= d3) & remain
    if any(is_b):
        result[is_b] = b[is_b]
        remain[is_b] = False

    # check if P in edge region of AB, if so return projection of P onto A
    vc = (d1 * d4) - (d3 * d2)
    is_ab = ((vc < tol.zero) &
             (d1 > -tol.zero) &
             (d3 < tol.zero) & remain)
    if any(is_ab):
        v = (d1[is_ab] / (d1[is_ab] - d3[is_ab])).reshape((-1, 1))
        result[is_ab] = a[is_ab] + (v * ab[is_ab])
        remain[is_ab] = False

    # check if P in vertex region outside C
    cp = points - c
    d5 = np.dot(ab * cp, ones)
    d6 = np.dot(ac * cp, ones)
    is_c = (d6 > -tol.zero) & (d5 <= d6) & remain
    if any(is_c):
        result[is_c] = c[is_c]
        remain[is_c] = False

    # check if P in edge region of AC, if so return projection of P onto AC
    vb = (d5 * d2) - (d1 * d6)
    is_ac = (vb < tol.zero) & (d2 > -tol.zero) & (d6 < tol.zero) & remain
    if any(is_ac):
        w = (d2[is_ac] / (d2[is_ac] - d6[is_ac])).reshape((-1, 1))
        result[is_ac] = a[is_ac] + w * ac[is_ac]
        remain[is_ac] = False

    # check if P in edge region of BC, if so return projection of P onto BC
    va = (d3 * d6) - (d5 * d4)
    is_bc = ((va < tol.zero) &
             ((d4 - d3) > - tol.zero) &
             ((d5 - d6) > -tol.zero) & remain)
    if any(is_bc):
        d43 = d4[is_bc] - d3[is_bc]
        w = (d43 / (d43 + (d5[is_bc] - d6[is_bc]))).reshape((-1, 1))
        result[is_bc] = b[is_bc] + w * (c[is_bc] - b[is_bc])
        remain[is_bc] = False

    # any remaining points must be inside face region
    if any(remain):
        # point is inside face region
        denom = 1.0 / (va[remain] + vb[remain] + vc[remain])
        v = (vb[remain] * denom).reshape((-1, 1))
        w = (vc[remain] * denom).reshape((-1, 1))
        # compute Q through its barycentric coordinates
        result[remain] = a[remain] + (ab[remain] * v) + (ac[remain] * w)

    return result

max_stars_repo_name: takuya-ki/wrs

max_issues_repo_name: takuya-ki/wrs

max_forks_repo_name: takuya-ki/wrs


text:
import gc
import logging
from multiprocessing import Pool, Lock, cpu_count
import os
import pathlib
import tempfile
import warnings
from typing import Union, Sequence, Tuple, List

import geopandas as gpd
import numpy as np
from pyproj import CRS, Transformer
from shapely import ops
from shapely.geometry import box, Polygon, MultiPolygon, LinearRing
from shapely.validation import explain_validity

from jigsawpy import jigsaw_msh_t, savemsh, savevtk

from ocsmesh.raster import Raster
from ocsmesh.mesh.mesh import Mesh

_logger = logging.getLogger(__name__)

class GeomCombine:

    _base_mesh_lock = Lock()
    def __init__(
            self,
            dem_files: Union[None, Sequence[Union[str, os.PathLike]]],
            out_file: Union[str, os.PathLike],
            out_format: str = "shapefile",
            mesh_file: Union[str, os.PathLike, None] = None,
            mesh_multipolygon: Union[MultiPolygon, Polygon] = None,
            ignore_mesh_final_boundary : bool = False,
            zmin: Union[float, None] = None,
            zmax: Union[float, None] = None,
            chunk_size: Union[int, None] = None,
            overlap: Union[int, None] = None,
            nprocs: int = -1,
            out_crs: Union[str, CRS] = "EPSG:4326",
            base_crs: Union[str, CRS] = None):

        self._calc_crs = None
        self._base_exterior = None

        nprocs = cpu_count() if nprocs == -1 else nprocs
        dem_files = [] if dem_files is None else dem_files

        self._operation_info = dict(
            dem_files=dem_files,
            out_file=out_file,
            out_format=out_format,
            mesh_file=mesh_file,
            mesh_mp_in=mesh_multipolygon,
            ignore_mesh=ignore_mesh_final_boundary,
            zmin=zmin,
            zmax=zmax,
            chunk_size=chunk_size,
            overlap=overlap,
            nprocs=nprocs,
            out_crs=out_crs,
            base_crs=base_crs)

    def run(self):

        dem_files = self._operation_info['dem_files']
        out_file = self._operation_info['out_file']
        out_format = self._operation_info['out_format']
        mesh_file = self._operation_info['mesh_file']
        mesh_mp_in = self._operation_info['mesh_mp_in']
        ignore_mesh = self._operation_info['ignore_mesh']
        zmin = self._operation_info['zmin']
        zmax = self._operation_info['zmax']
        chunk_size = self._operation_info['chunk_size']
        overlap = self._operation_info['overlap']
        nprocs = self._operation_info['nprocs']
        out_crs = self._operation_info['out_crs']
        base_crs = self._operation_info['base_crs']

        out_dir = pathlib.Path(out_file).parent
        out_dir.mkdir(exist_ok=True, parents=True)

        # Warping takes time; to optimize, only warp rasters
        # during calculation of polygons if needed. Otherwise
        # only warp polygon before writing to file
        if isinstance(out_crs, str):
            out_crs = CRS.from_user_input(out_crs)
        if isinstance(base_crs, str):
            base_crs = CRS.from_user_input(base_crs)
        all_crs = set(Raster(dem).crs for dem in dem_files)
        self._calc_crs = out_crs
        if len(all_crs) == 1:
            self._calc_crs = list(all_crs)[0]
            _logger.info(
                f"All DEMs have the same CRS:"
                f" {self._calc_crs.to_string()}")

        base_mult_poly = None
        if mesh_mp_in:
            # Assumption: If base_mult_poly is provided, it's in
            # base_crs if not None, else in out_crs
            base_mult_poly = self._get_valid_multipolygon(mesh_mp_in)
            if base_crs is None:
                base_crs = out_crs
            if not base_crs.equals(self._calc_crs):
                _logger.info("Reprojecting base polygon...")
                transformer = Transformer.from_crs(
                    base_crs, self._calc_crs, always_xy=True)
                base_mult_poly = ops.transform(
                        transformer.transform, base_mult_poly)

        elif mesh_file and pathlib.Path(mesh_file).is_file():
            _logger.info("Creating mesh object from file...")
            base_mesh = Mesh.open(mesh_file, crs=base_crs)
            mesh_crs = base_mesh.crs
            # Assumption: If mesh_crs is not defined, mesh is in
            # base_crs if not None, else inout_crs
            if base_crs is None:
                if mesh_crs:
                    base_crs = mesh_crs
                else:
                    base_crs = out_crs
            if not self._calc_crs.equals(base_crs):
                _logger.info("Reprojecting base mesh...")
                transformer = Transformer.from_crs(
                    base_crs, self._calc_crs, always_xy=True)
                xy = base_mesh.coord
                xy = np.vstack(
                    transformer.transform(xy[:, 0], xy[:, 1])).T
                base_mesh.coord[:] = xy

            _logger.info("Done")

            _logger.info("Getting mesh hull polygons...")
            base_mult_poly = base_mesh.hull.multipolygon()
            _logger.info("Done")

            base_mult_poly = self._get_valid_multipolygon(base_mult_poly)

        if base_mult_poly:
            # NOTE: This needs to happen once and before any
            # modification to basemesh happens (due to overlap
            # w/ DEM, etc.). Exterior of base mesh is used for
            # raster clipping
            #
            # TODO: Add buffer for base mesh exterior in case there
            # was erosion and we want to make sure new DEMs futher
            # inland are considered (?)
            self._base_exterior = MultiPolygon(
                    list(ops.polygonize(
                        [poly.exterior for poly in base_mult_poly])))

        z_info = {}
        if zmin is not None:
            z_info['zmin'] = zmin
        if zmax is not None:
            z_info['zmax'] = zmax

        poly_files_coll = []
        _logger.info(f"Number of processes: {nprocs}")
        with tempfile.TemporaryDirectory(dir=out_dir) as temp_dir, \
                tempfile.NamedTemporaryFile() as base_file:

            if base_mult_poly:
                base_mesh_path = base_file.name
                self._multipolygon_to_disk(
                    base_mesh_path, base_mult_poly, fix=False)
            else:
                base_mesh_path = None
            base_mult_poly = None

            _logger.info("Processing DEM priorities ...")
            # Process priority: priority is based on the order,
            # the last input has the highest priority
            # (i.e. lowest priority number)
            priorities = list((range(len(dem_files))))[::-1]
            # TODO: Needs some code refinement for bbox issue
#            priority_args = []
#            for priority, dem_file in zip(priorities, dem_files):
#                priority_args.append(
#                    (priority, temp_dir, dem_file, chunk_size, overlap))
#
#            with Pool(processes=nprocs) as p:
#                p.starmap(self._process_priority, priority_args)
#            p.join()

            _logger.info("Processing DEM contours ...")
            # Process contours
            if nprocs > 1:
                parallel_args = []
                for priority, dem_file in zip(priorities, dem_files):
                    parallel_args.append(
                        (base_mesh_path, temp_dir,
                         priority, dem_file,
                         z_info, chunk_size, overlap))
                with Pool(processes=nprocs) as p:
                    poly_files_coll.extend(
                        p.starmap(
                            self._parallel_get_polygon_worker,
                            parallel_args))
                p.join()
            else:
                poly_files_coll.extend(
                    self._serial_get_polygon(
                        base_mesh_path, temp_dir,
                        priorities, dem_files,
                        z_info, chunk_size, overlap))

            _logger.info("Generating final boundary polygon...")
            # If a DEM doesn't intersect domain None will
            # be returned by worker
            poly_files_coll = [i for i in poly_files_coll if i]
            if base_mesh_path is not None and not ignore_mesh:
                poly_files_coll.append(base_mesh_path)

            rasters_gdf = gpd.GeoDataFrame(
                    columns=['geometry'],
                    crs=self._calc_crs
                )
            for feather_f in poly_files_coll:
                rasters_gdf = rasters_gdf.append(
                    gpd.GeoDataFrame(
                        {'geometry': self._read_multipolygon(
                                                feather_f)
                        },
                        crs=self._calc_crs
                        ),
                    ignore_index=True)

            # The assumption is this returns polygon or multipolygon
            fin_mult_poly = rasters_gdf.unary_union
            _logger.info("Done")

        # If DEM is not inside input base polygon, the end results
        # is None
        if fin_mult_poly:
            # Get a clean multipolygon to write to output
            # Is this necessary? It can be expensive if geom is not valid
            fin_mult_poly = self._get_valid_multipolygon(fin_mult_poly)

            self._write_to_file(
                    out_format, out_file, fin_mult_poly, out_crs)

        self._base_exterior = None

    def _get_valid_multipolygon(
            self,
            polygon: Union[Polygon, MultiPolygon]
            ) -> MultiPolygon:

        if not polygon.is_valid:
            polygon = ops.unary_union(polygon)

            if not polygon.is_valid:
                polygon = polygon.buffer(0)

            if not polygon.is_valid:
                raise ValueError(explain_validity(polygon))

        if isinstance(polygon, Polygon):
            polygon = MultiPolygon([polygon])

        return polygon

    def _multipolygon_to_disk(
            self,
            path: Union[str, os.PathLike],
            multipolygon: MultiPolygon,
            fix: bool = True):

        if fix:
            multipolygon = self._get_valid_multipolygon(
                    multipolygon)

        if isinstance(multipolygon, Polygon):
            # In case fix is not True, we need to make sure it's
            # a multipolygon instead of polygon for dataframe creation
            multipolygon = MultiPolygon([multipolygon])

        gpd.GeoDataFrame({'geometry': multipolygon}).to_feather(path)

    def _read_multipolygon(
            self,
            path: Union[str, os.PathLike],
            fix: bool = True
            ) -> MultiPolygon:

        multipolygon = MultiPolygon(
                list(gpd.read_feather(path).geometry))

        if fix:
            multipolygon = self._get_valid_multipolygon(
                    multipolygon)

        return multipolygon

    def _read_to_geodf(
            self,
            path: Union[str, os.PathLike],
            ) -> gpd.GeoDataFrame:

        gdf = gpd.read_feather(path)

        return gdf

    def _process_priority(
            self,
            priority: int,
            temp_dir: Union[str, os.PathLike],
            dem_path: Union[str, os.PathLike],
            chunk_size: Union[int, None] = None,
            overlap: Union[int, None] = None):

        rast = Raster(
                dem_path,
                chunk_size=chunk_size,
                overlap=overlap)
        # Can cause issue with bbox(?)
        if not self._calc_crs.equals(rast.crs):
            rast.warp(dst_crs=self._calc_crs)

        pri_dt_path = (
            pathlib.Path(temp_dir) / f'dem_priority_{priority}.feather')

        pri_mult_poly = MultiPolygon([box(*rast.src.bounds)])

        self._multipolygon_to_disk(
                pri_dt_path, pri_mult_poly)

    def _serial_get_polygon(
            self,
            base_mesh_path: Union[str, os.PathLike, None],
            temp_dir: Union[str, os.PathLike],
            priorities: Sequence[int],
            dem_files: Sequence[Union[str, os.PathLike]],
            z_info: dict = {},
            chunk_size: Union[int, None] = None,
            overlap: Union[int, None] = None):

        _logger.info("Getting DEM info")
        poly_coll = []
        for priority, dem_path in zip(priorities, dem_files):
            _logger.info(f"Processing {dem_path} ...")
            if not pathlib.Path(dem_path).is_file():
                warnings.warn(f"File {dem_path} not found!")
                _logger.debug(f"File {dem_path} not found!")
                continue

            # Calculate Polygon
            _logger.info("Loading raster from file...")
            rast = Raster(
                    dem_path,
                    chunk_size=chunk_size,
                    overlap=overlap)
            # Can cause issue with bbox(?)
            if not self._calc_crs.equals(rast.crs):
                rast.warp(dst_crs=self._calc_crs)

            _logger.info("Clipping to basemesh size if needed...")
            rast_box = box(*rast.src.bounds)
            if base_mesh_path is not None:
                # NOTE: We use the exterior from the earlier calc
                if self._base_exterior and not rast_box.within(self._base_exterior):
                    if not rast_box.intersects(self._base_exterior):
                        _logger.info(
                            f"{dem_path} is ignored due to base mesh...")
                        continue

                    _logger.info(
                        f"{dem_path} needs clipping by base mesh...")
                    rast.clip(self._base_exterior)
                    rast_box = box(*rast.src.bounds)

            # Processing raster
            _logger.info("Creating geom from raster...")

            _logger.info("Getting polygons from geom...")
            geom_mult_poly = rast.get_multipolygon(**z_info)
            geom_mult_poly = self._get_valid_multipolygon(
                    geom_mult_poly)

            if base_mesh_path is not None:
                _logger.info("Subtract DEM bounds from base mesh polygons...")
                self._base_mesh_lock.acquire()
                try:
                    # Get a valid multipolygon from disk
                    base_mult_poly = self._read_multipolygon(
                            base_mesh_path)

                    # Get valid multipolygon after operation and write
                    base_mult_poly = base_mult_poly.difference(
                            rast_box)
                    self._multipolygon_to_disk(
                            base_mesh_path, base_mult_poly)

                finally:
                    self._base_mesh_lock.release()

            # TODO: Needs some code refinement due to bbox
            # Processing DEM priority
#            priority_geodf = gpd.GeoDataFrame(
#                    columns=['geometry'],
#                    crs=self._calc_crs)
#            for p in range(priority):
#                higher_pri_path = (
#                    pathlib.Path(temp_dir) / f'dem_priority_{p}.feather')
#
#                if higher_pri_path.is_file():
#                    priority_geodf = priority_geodf.append(
#                             self._read_to_geodf(higher_pri_path))
#
#            if len(priority_geodf):
#                op_res = priority_geodf.unary_union
#                pri_mult_poly = MultiPolygon()
#                if isinstance(op_res, MultiPolygon):
#                    pri_mult_poly = op_res
#                else:
#                    pri_mult_poly = MultiPolygon([op_res])
#
#
#                if rast_box.within(pri_mult_poly):
#                    _logger.info(
#                        f"{dem_path} is ignored due to priority...")
#                    continue
#
#                if rast_box.intersects(pri_mult_poly):
#                    _logger.info(
#                        f"{dem_path} needs clipping by priority...")
#
#                    # Clipping raster can cause problem at
#                    # boundaries due to difference in pixel size
#                    # between high and low resolution rasters
#                    # so instead we operate on extracted polygons
#                    geom_mult_poly = geom_mult_poly.difference(
#                            pri_mult_poly)

            # Write geometry multipolygon to disk
            temp_path = (
                    pathlib.Path(temp_dir)
                    / f'{pathlib.Path(dem_path).name}.feather')

            try:
                self._multipolygon_to_disk(temp_path, geom_mult_poly)
                poly_coll.append(temp_path)
            except:
                warnings.warn(f"Error writing {temp_path} to disk")

            # Multipolygon takes a lot of memory
            del geom_mult_poly
            gc.collect(2)

        return poly_coll

    def _parallel_get_polygon_worker(
            self,
            base_mesh_path: Union[str, os.PathLike, None],
            temp_dir: Union[str, os.PathLike],
            priority: int,
            dem_file: Union[str, os.PathLike],
            z_info: dict = {},
            chunk_size: Union[int, None] = None,
            overlap: Union[int, None] = None):

        poly_coll_files = self._serial_get_polygon(
            base_mesh_path, temp_dir, [priority], [dem_file],
            z_info, chunk_size, overlap)

        # Only one item passed to serial code at most
        return poly_coll_files[0] if poly_coll_files else None

    def _linearring_to_vert_edge(
            self,
            coords: List[Tuple[float, float]],
            edges: List[Tuple[int, int]],
            lin_ring: LinearRing):

        '''From shapely LinearRing get coords and edges'''

        # NOTE: This function mutates coords and edges

        # TODO: Move to utils?
        idx_b = len(coords)
        coords.extend(coord for coord in lin_ring.coords)
        # Last coord is the same as first in a ring
        coords.pop()
        idx_e = len(coords) - 1
        n_idx = len(coords)

        edges.extend([
            (i, (i + 1) % n_idx + idx_b * ((i + 1) // n_idx))
            for i in range(idx_b, idx_e + 1)])

    def _write_to_file(
            self, out_format, out_file, multi_polygon, crs):

        _logger.info(f"Writing for file ({out_format}) ...")

        # TODO: Check for correct extension on out_file
        if out_format == "shapefile":
            gdf = gpd.GeoDataFrame(
                    {'geometry': multi_polygon},
                    crs=self._calc_crs
                    )
            if not crs.equals(self._calc_crs):
                _logger.info(
                    f"Project from {self._calc_crs.to_string()} to"
                    f" {crs.to_string()} ...")
                gdf = gdf.to_crs(crs)
            gdf.to_file(out_file)

        elif out_format == "feather":
            gdf = gpd.GeoDataFrame(
                    {'geometry': multi_polygon},
                    crs=self._calc_crs
                    )
            if not crs.equals(self._calc_crs):
                _logger.info(
                    f"Project from {self._calc_crs.to_string()} to"
                    f" {crs.to_string()} ...")
                gdf = gdf.to_crs(crs)
            gdf.to_feather(out_file)

        elif out_format in ("jigsaw", "vtk"):

            if not crs.equals(self._calc_crs):
                _logger.info(
                    f"Project from {self._calc_crs.to_string()} to"
                    f" {crs.to_string()} ...")
                transformer = Transformer.from_crs(
                    self._calc_crs, crs, always_xy=True)
                multi_polygon = ops.transform(
                        transformer.transform, multi_polygon)

            msh = jigsaw_msh_t()
            msh.ndims = +2
            msh.mshID = 'euclidean-mesh'

            coords = []
            edges = []
            for polygon in multi_polygon:
                self._linearring_to_vert_edge(
                        coords, edges, polygon.exterior)
                for interior in polygon.interiors:
                    self._linearring_to_vert_edge(
                            coords, edges, interior)

            msh.vert2 = np.array(
                [(i, 0) for i in coords],
                dtype=jigsaw_msh_t.VERT2_t)
            msh.edge2 = np.array(
                [(i, 0) for i in edges],
                dtype=jigsaw_msh_t.EDGE2_t)

            if out_format == "jigsaw":
                savemsh(out_file, msh)

            elif out_format == "vtk":
                savevtk(out_file, msh)

        else:
            raise NotImplementedError(f"Output type {out_format} is not supported")

        _logger.info("Done")

max_stars_repo_name: yosoyjay/OCSMesh

max_issues_repo_name: yosoyjay/OCSMesh

max_forks_repo_name: noaa-ocs-modeling/geomesh


text:
import glob
import numpy as np
import pickle
from tqdm import tqdm
import os

class FolderDumper():
	def __init__(self, outpath):
		self.outpath = outpath
		self.result = []

	def push_folder(self, folder_path):
		res = []
		folders = glob.glob(os.path.join(folder_path,'*'))
		folders = sorted(folders)
		for i in tqdm(folders):
			imgs = glob.glob(os.path.join(i, '*.*'))
			res.append(imgs)
		self.result.append({'type':'folder', 'data':res})

	def push_sulio(self, path):
		self.result.append({'type':'sulio', 'data':path})

	def push_mxrec(self, path):
		self.result.append({'type':'mxrec', 'data':path})

	def finish(self):
		pickle.dump(self.result, open(self.outpath + '.pkl', 'wb'))

dumper = FolderDumper('PesWebface_r1_id_old_yong')
dumper.push_sulio('WebfaceRound1')
# dumper.push_folder('pad_face_20210511/pad_face_20210511')
dumper.push_folder('ID_faces_cleaned/old')
dumper.push_folder('ID_faces_cleaned/yong')
dumper.finish()


text:
from random import choice
import numpy as np

def empty_position( board_state):
    board_state = np.array( board_state)
    valid_moves_loc = []
    directions = ( ( -1, -1), ( -1, 0), ( -1, 1), ( 0, -1), ( 0, 1), ( 1, -1), ( 1, 0), ( 1, 1))
    non_zeros = np.argwhere( board_state != 0)

    for ele in non_zeros:
        row = ele[ 0]
        col = ele[ 1]

        for direction in directions:
            this_row, this_col = row + direction[ 0], col + direction[ 1]

            if ( 0 <= this_row < 8 and 0 <= this_col < 8
               and board_state[ this_row][ this_col] == 0
               and ( this_row, this_col) not in valid_moves_loc):
                valid_moves_loc.append( ( this_row, this_col))
    return valid_moves_loc

def compute_available_move( board_state, empty_list, specific_player):
        valid_moves = []
        directions = ( ( -1, -1), ( -1, 0), ( -1, 1), ( 0, -1), ( 0, 1), ( 1, -1), ( 1, 0), ( 1, 1))

        for ( row, col) in empty_list:

            for idx, direction in enumerate( directions):
                this_row, this_col = row + direction[ 0], col + direction[ 1]

                if ( 0 <= this_row < 8 and 0 <= this_col < 8
                     and board_state[ this_row][ this_col] == -specific_player):

                     while True:
                        this_row += direction[ 0]
                        this_col += direction[ 1]

                        if 0 <= this_row < 8 and 0 <= this_col < 8:

                            if board_state[ this_row][ this_col] == specific_player:
                                valid_moves.append( ( row, col, idx))
                                break

                            elif board_state[ this_row][ this_col] == -specific_player:
                                continue

                            else:
                                break

                        else:
                            break

        valid_moves = np.array( valid_moves)
        return valid_moves

def flip_direction( board_state, cheer_row, cheer_col, player):
    directions = ( ( -1, -1), ( -1, 0), ( -1, 1), ( 0, -1), ( 0, 1), ( 1, -1), ( 1, 0), ( 1, 1))
    explore_direction = []

    for direction in directions:
        row = cheer_row
        col = cheer_col

        while True:
            row += direction[ 0]
            col += direction[ 1]

            if 0 <= row < 8 and 0 <= col < 8:

                if board_state[ row][ col] == -player:
                    continue

                elif board_state[ row][ col] != 0:
                    explore_direction.append( direction)
                    break

                else:
                    break

            else:
                break

    return explore_direction

class Player:
    def __init__(self):
        self.name = "Player"

    def move( self, board_inf):
        """
        Args:
            board_inf:
                 [0] - valid_moves: 可以下的地方，它會是一個二維的 list ex:[[1,2],[2,2]]
                 [1] - board_state: 當前棋盤狀況
                 [2] - player_no  : 你先攻的話就是 1(O),反之 -1(X)
                 [3] - total_step : 現在下到第幾步 (Hint: 對於黑白棋而言，解尾盤比較重要)
        return:
            your moves: 你要下哪裡，它會是一個一維的 list ex:[1,2]
        """
        # print( board_inf[ 1])
        max_weights = [ [ 100, -50, 50, 40, 40, 50, -50, 100],
                        [ -50, -80, 50,  5,  5, 50, -80, -50],
                        [  50,  50, 60,  3,  3, 60,  50,  50],
                        [  40,   5,  3,  0,  0,  3,   5,  40],
                        [  40,   5,  3,  0,  0,  3,   5,  40],
                        [  50,  50, 50,  3,  3, 60,  50,  50],
                        [ -50, -80, 60,  5,  5, 50, -80, -50],
                        [ 100, -50, 50, 40, 40, 50, -50, 100]]

        best_score = float( "-inf")

        # 計算目前棋盤能下的位置 與 分類黑棋能下位置 and 白棋能下位置
        valid_position_loc = empty_position( board_state= board_inf[ 1])
        valid_position = { player: compute_available_move( board_state= board_inf[ 1], empty_list= valid_position_loc, specific_player= player) for player in [ -1, 1]}

        if board_inf[ 3] < 58:
            for empty_ind, empty_col, _ in valid_position[ board_inf[ 2]]:
                now_board = board_inf[ 1].copy()

                # 假設下在 ( empty_ind, empty_col) 位置
                now_board[ empty_ind][ empty_col] = board_inf[ 2]

                # 下完棋之後，重新整理棋盤的情況
                # 找尋可以翻棋的方向
                flip_direction_list = flip_direction( board_state= now_board, cheer_row= empty_ind, cheer_col= empty_col, player= board_inf[ 2])

                # 重新整理棋盤的情況
                for diretion in flip_direction_list:
                    this_row, this_col = empty_ind, empty_col

                    while True:
                        this_row += diretion[ 0]
                        this_col += diretion[ 1]

                        if 0 <= this_row < 8 and 0 <= this_col < 8:
                            if now_board[ this_row][ this_col] == -board_inf[ 2]:
                                now_board[ this_row][ this_col] = board_inf[ 2]
                            else:
                                break
                        else:
                            break

                # 紀錄第一層權重數值
                layer_1 = max_weights[ empty_ind][ empty_col]

                ## 計算 human 下一子後 棋盤能下的位置 與 分類黑棋能下位置 and 白棋能下位置
                valid_position_loc_ai = empty_position( board_state= now_board)
                valid_position_ai = { player: compute_available_move( board_state= now_board, empty_list= valid_position_loc_ai, specific_player= player) for player in [ -1, 1]}

                for ai_empty_ind, ai_empty_col, _ in valid_position_ai[ -board_inf[ 2]]:
                    # 假設 ai 下在 ( ai_empty_ind, ai_empty_col) 位置
                    now_board[ ai_empty_ind][ ai_empty_col] = -board_inf[ 2]

                    # 下完棋之後，重新整理棋盤的情況
                    # 找尋可以翻棋的方向
                    flip_direction_list = flip_direction( board_state= now_board, cheer_row= ai_empty_ind, cheer_col= ai_empty_col, player= -board_inf[ 2])

                    # 重新整理棋盤的情況
                    for diretion in flip_direction_list:
                        this_row, this_col = empty_ind, empty_col

                        while True:
                            this_row += diretion[ 0]
                            this_col += diretion[ 1]

                            if 0 <= this_row < 8 and 0 <= this_col < 8:
                                if now_board[ this_row][ this_col] == board_inf[ 2]:
                                    now_board[ this_row][ this_col] = -board_inf[ 2]
                                else:
                                    break
                            else:
                                break

                    ## 計算 ai 下一子後 棋盤能下的位置 與 分類黑棋能下位置 and 白棋能下位置
                    valid_position_loc_hm = empty_position( board_state= now_board)
                    valid_position_hm = { player: compute_available_move( board_state= now_board, empty_list= valid_position_loc, specific_player= player) for player in [ -1, 1]}

                    now_board[ ai_empty_ind][ ai_empty_col] = 0

                    for hm_empty_ind, hm_empty_col, _ in valid_position_hm[ board_inf[ 2]]:
                        layer_2 = max_weights[ hm_empty_ind][ hm_empty_col]

                        # 理論上，會希望都走皆是權重最大的地方
                        if layer_1 + layer_2 > best_score:
                            best_score = layer_1 + layer_2
                            global best_position
                            best_position = ( empty_ind, empty_col)

                now_board[ empty_ind][ empty_col] = 0

            # print( best_position, "", sep= "\n")
            for item in board_inf[0]:
                if item[0] == best_position[0] and item[1] == best_position[1]:
                    return best_position
            return board_inf[0][0]

        else:
            return choice( board_inf[ 0])

max_stars_repo_name: Fritingo/hw

max_issues_repo_name: Fritingo/hw

max_forks_repo_name: Fritingo/hw


text:
import numpy as np

from PuzzleLib import Config
from PuzzleLib.Backend import gpuarray

from PuzzleLib.Modules.Module import ModuleError
from PuzzleLib.Modules.DeconvND import DeconvND

class Deconv2D(DeconvND):
	def __init__(self, inmaps, outmaps, size, stride=1, pad=0, dilation=1, postpad=0, wscale=1.0, useBias=True,
				 name=None, initscheme=None, empty=False, groups=1):
		super().__init__(
			2, inmaps, outmaps, size, stride, pad, dilation, postpad, wscale, useBias, name, initscheme, empty, groups
		)
		self.registerBlueprint(locals())

	def checkDataShape(self, shape):
		if len(shape) != 4:
			raise ModuleError("Data must be 4d tensor")

		_, inmaps, _, _ = shape
		if inmaps != self.W.shape[0]:
			raise ModuleError("Data has %d maps (expected: %d)" % (inmaps, self.W.shape[0]))

	def dataShapeFrom(self, shape):
		batchsize, inmaps, inh, inw = shape
		_, outmaps, fh, fw = self.W.shape

		hpad, wpad = self.pad
		hpostpad, wpostpad = self.postpad

		hdilation, wdilation = self.dilation
		hstride, wstride = self.stride

		outmaps *= self.groups
		outh = (inh - 1) * hstride + hdilation * (fh - 1) - 2 * hpad + 1 + hpostpad
		outw = (inw - 1) * wstride + wdilation * (fw - 1) - 2 * wpad + 1 + wpostpad

		return batchsize, outmaps, outh, outw

	def checkGradShape(self, shape):
		if len(shape) != 4:
			raise ModuleError("Grad must be 4d tensor")

		_, outmaps, outh, outw = shape
		_, _, fh, fw = self.W.shape

		hpad, wpad = self.pad
		hdilation, wdilation = self.dilation

		if outmaps != self.W.shape[1] * self.groups:
			raise ModuleError("Grad has %d maps (expected: %d)" % (outmaps, self.W.shape[1] * self.groups))

		if outh + 2 * hpad < hdilation * (fh - 1) + 1:
			raise ModuleError(
				"Grad maps height is too small (got %d, expected at least %d)" %
				(outh + 2 * hpad, hdilation * (fh - 1) + 1)
			)

		if outw + 2 * wpad < wdilation * (fw - 1) + 1:
			raise ModuleError(
				"Grad maps width is too small (got %d, expected at least %d)" %
				(outw + 2 * wpad, wdilation * (fw - 1) + 1)
			)

	def gradShapeFrom(self, shape):
		batchsize, outmaps, outh, outw = shape
		inmaps, _, fh, fw = self.W.shape

		hpad, wpad = self.pad
		hdilation, wdilation = self.dilation
		hstride, wstride = self.stride

		inh = (outh + 2 * hpad - hdilation * (fh - 1) - 1) // hstride + 1
		inw = (outw + 2 * wpad - wdilation * (fw - 1) - 1) // wstride + 1

		return batchsize, inmaps, inh, inw

def unittest():
	multiInMapsTest()
	multiOutMapsTest()

	if Config.backend in {Config.Backend.cuda, Config.Backend.hip}:
		multiMapsWithPadsTest()

	trainTest()

def multiInMapsTest():
	batchsize, inmaps, h, w = 1, 2, 10, 10
	outmaps, stride, size, postpad = 1, 2, 4, 1

	hostData = np.random.randn(batchsize, inmaps, h, w).astype(np.float32)
	data = gpuarray.to_gpu(hostData)

	deconv = Deconv2D(inmaps, outmaps, size, stride=2, postpad=postpad)
	deconv(data)

	hostW, hostBias = deconv.W.get(), deconv.b.get()

	hostOutData = np.zeros(deconv.data.shape).astype(np.float32)
	hostSliceData = hostOutData[:, :, :-postpad, :-postpad]

	for k in range(inmaps):
		for i in range(0, hostSliceData.shape[2] - size + 1, stride):
			for j in range(0, hostSliceData.shape[3] - size + 1, stride):
				hostOutData[0, 0, i:size + i, j:size + j] += hostW[k, 0] * hostData[0, k, i // stride, j // stride]

		hostSliceData[0, 0] += hostBias[0, 0]

	assert np.allclose(hostOutData, deconv.data.get())

def multiOutMapsTest():
	batchsize, inmaps, h, w = 1, 1, 2, 2
	outmaps = 2
	stride = 2
	size = 4

	hostData = np.random.randn(batchsize, inmaps, h, w).astype(np.float32)
	data = gpuarray.to_gpu(hostData)

	deconv = Deconv2D(inmaps, outmaps, size, stride=stride)
	deconv(data)

	hostW, hostBias = deconv.W.get(), deconv.b.get()
	hostOutData = np.zeros(deconv.data.shape).astype(np.float32)

	for k in range(outmaps):
		for i in range(0, hostOutData.shape[2] - size + 1, stride):
			for j in range(0, hostOutData.shape[3] - size + 1, stride):
				hostOutData[0, k, i:size + i, j:size + j] += hostW[0, k] * hostData[0, 0, i // stride, j //stride]

		hostOutData[0, k] += hostBias[0, k]

	assert np.allclose(hostOutData, deconv.data.get())

def multiMapsWithPadsTest():
	batchsize, inmaps, h, w = 3, 4, 2, 2
	outmaps, size, stride, pad, dilation = 4, 3, 2, 1, 2

	hostData = np.random.randn(batchsize, inmaps, h, w).astype(np.float32)
	data = gpuarray.to_gpu(hostData)

	deconv = Deconv2D(inmaps, outmaps, size=size, stride=stride, pad=pad, dilation=dilation, initscheme="gaussian")
	deconv(data)

	hostW, hostBias = deconv.W.get(), deconv.b.get()
	dl = dilation

	hostOutData = np.zeros(
		deconv.data.shape[:2] + (deconv.data.shape[2] + 2 * pad, deconv.data.shape[3] + 2 * pad), dtype=np.float32
	)

	for c in range(outmaps):
		hostOutData[:, c, :, :] = hostBias[0, c, 0, 0]

	for b in range(batchsize):
		for oc in range(outmaps):
			for ic in range(inmaps):
				for y in range(h):
					for x in range(w):
						for dy in range(size):
							for dx in range(size):
								hostOutData[b,oc,y*stride+dy*dl,x*stride+dx*dl] += hostW[ic,oc,dy,dx]*hostData[b,ic,y,x]

	assert np.allclose(hostOutData[:, :, pad:-pad, pad:-pad], deconv.data.get())

	hostGrad = np.random.randn(*deconv.data.shape).astype(np.float32)
	grad = gpuarray.to_gpu(hostGrad)

	deconv.backward(grad)
	hostExtGrad = np.zeros(grad.shape[:2] + (grad.shape[2] + 2 * pad, grad.shape[3] + 2 * pad), dtype=np.float32)

	hostExtGrad[:, :, pad:-pad, pad:-pad] = hostGrad
	hostGrad = hostExtGrad

	hostInGrad = np.zeros(hostData.shape, dtype=np.float32)

	for b in range(batchsize):
		for ic in range(inmaps):
			for oc in range(outmaps):
				for y in range(h):
					for x in range(w):
						for dy in range(size):
							for dx in range(size):
								hostInGrad[b,ic,y,x] += hostGrad[b,oc,y*stride+dy*dl, x*stride+dx*dl]*hostW[ic,oc,dy,dx]

	assert np.allclose(hostInGrad, deconv.grad.get())

	hostWGrad = np.zeros(deconv.getVar("W").grad.shape, dtype=np.float32)
	for b in range(batchsize):
		for ic in range(inmaps):
			for oc in range(outmaps):
				for dy in range(size):
					for dx in range(size):
						for y in range(h):
							for x in range(w):
								hostWGrad[ic,oc,dy,dx]+=hostGrad[b,oc,y*stride+dy*dl,x*stride+dx*dl]*hostData[b,ic,y,x]

	assert np.allclose(hostWGrad, deconv.getVar("W").grad.get())

	hostBiasGrad = np.empty(hostBias.shape, dtype=np.float32)
	for oc in range(outmaps):
		hostBiasGrad[0, oc, 0, 0] = np.sum(hostGrad[:, oc, :, :])

	assert np.allclose(hostBiasGrad, deconv.getVar("b").grad.get())

def trainTest():
	batchsize, inmaps, h, w = 5, 5, 2, 2
	outmaps = 1
	size = 8

	data = gpuarray.to_gpu(np.random.normal(0.0, 1.0, (batchsize, inmaps, h, w)).astype(np.float32))
	deconv = Deconv2D(inmaps, outmaps, size)

	from PuzzleLib.Cost.MSE import MSE
	mse = MSE()

	target = gpuarray.to_gpu(np.random.normal(0.0, 1.0, (batchsize, outmaps, 9, 9)).astype(np.float32))

	for i in range(100):
		learnRate = 1e-2

		deconv(data)
		error, grad = mse(deconv.data, target)

		deconv.backward(grad)
		deconv.updateParams(learnRate)

		if (i + 1) % 5 == 0:
			print("Iteration #%d error: %s" % (i + 1, error))

if __name__ == "__main__":
	unittest()


text:
from collections import deque
from os import system
import numpy as np
import win32ui
from grabber import Grabber
import time
import os
import sys
from directkeys import W,A,S,D,P,U,E,Q,T,L,I,R,F1,F2,F3,F11,NUM1,NUM2,NUM4,SPACE,G,E,PressKey,ReleaseKey,ReleaseKeys,PressAndRelease,PressAndFastRelease
from numpy import genfromtxt
from windowMgr import WindowMgr
import os
import subprocess
import threading
from gym import spaces
import math
import pickle

BOSSAREA="400100"
DARKSOULSDIR="C:\Program Files (x86)\Steam\steamapps\common\DARK SOULS III\Game\DarkSoulsIII.exe"
BONFIREAREA="400101"
FRAME_DIFF=0.2
SAVE_PROGRESS_SHADOWPLAY=False
SAVE_KILLS_SHADOWPLAY=True
NO_ACTION=[0,0]

HERO_BASE_HP=454
LUDEX_BASE_HP=1037
HEALTH_REWARD_MULTIPLIER=2.5
REWARD_DISTANCE=5
ESTUS_NEGATIVE_REWARD=0.3
PARRY_REWARD=0.1
TIMESTEPS_DEFENSIVE_BEHAVIOR=200
DEFENSIVE_BEHAVIOR_NEGATIVE_REWARD =0.002

start_time=-1
not_responding_lock=threading.Lock()

areaKey="locationArea"
charHpKey="heroHp"
charSpKey="heroSp"
bossHpKey="targetedEntityHp"

num_state_scalars=60
num_history_states=5
num_prev_animations=1

parryAnimationName='DamageParryEnemy1'

def parse_val(value):
    try:
        val=float(value)
        return val
    except ValueError:
        if value=="??":
            return 0
        return value

class dsgym:

    observation_space=spaces.Box(-100,1000,shape=(num_history_states*num_state_scalars,))
    #1) WASD Keys:  Discrete 5  - NOOP[0], W[1], A[2], S[3], D[4]  - params: min: 0, max: 4
    #2) Action:     Discrete 6  - NOOP[0], Jump[1], Parry[2], Block[3], Attack[4], estus[5] - params: min: 0, max: 5
    action_space=spaces.MultiDiscrete([5,6])
    metadata=None
    def __init__(self):
        self.bossAnimationSet = []
        self.charAnimationSet = []
        self.best_so_far=-100
        self.set_initial_state()
        self.spawnCheckRespondingThread()
        self.logfile = open("gameInfo.txt", "r", encoding="utf-8")

        self.paused=False

    def set_initial_state(self):
        self.prev_input_actions = NO_ACTION
        self.prev_char_animations = deque([],maxlen=num_prev_animations)
        self.prev_boss_animations = deque([],maxlen=num_prev_animations)
        self.prev_state = deque([], maxlen=num_history_states)
        self.fill_frame_buffer=True
        self.episode_rew=0
        self.episode_len=0
        self.bossHpLastFrame=LUDEX_BASE_HP
        self.bossAnimationLastFrame='??'
        self.bossAnimationFrameCount=0
        self.charHpLastFrame=HERO_BASE_HP
        self.charAnimationLastFrame='??'
        self.charAnimationFrameCount=0
        self.timesincecharacterattack=0
        self.timesincebossattack=0
        self.timesincebosslosthp=0
        self.timesinceherolosthp=0
        self.timesinceheroparry=0
        self.numEstusLastFrame=0
        self.info={}
        for _ in range(num_prev_animations):
            self.prev_boss_animations.append(0)
            self.prev_char_animations.append(0)

    def unpause_wrapper(self):
        if(self.paused):
            PressAndFastRelease(U)
            self.paused=False

    def pause_wrapper(self):
        PressAndRelease(P)
        self.paused=True
    def speed_up_wrapper(self):
        PressAndRelease(I)
    def normal_speed_wrapper(self):
        PressAndFastRelease(U)

    def notresponding(self,name):
        #os.system('tasklist /FI "IMAGENAME eq %s" /FI "STATUS eq not responding" > tmp.txt' % name)
        #x = subprocess.check_output()
        a = subprocess.Popen('tasklist /FI "IMAGENAME eq %s" /FI "STATUS eq running"' % name,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        a=a.communicate()[0].decode("utf-8")
        b = subprocess.Popen('tasklist /FI "IMAGENAME eq WerFault.exe" /FI "STATUS eq running"',stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        b=b.communicate()[0].decode("utf-8")
        c = subprocess.Popen('tasklist /FI "IMAGENAME eq %s" /FI "STATUS ne running"' % name,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        c=c.communicate()[0].decode("utf-8")
        #tmp.close()
        if c.split("\n")[-2].startswith(name) or "INFO:" not in b:
            return True
        elif a.split("\n")[-2].startswith(name):
            return False
        else:
            return True

    def setDsInFocus(self):
        self.releaseAll()
        w=WindowMgr()
        w.find_window_wildcard(".*ARK SOULS.*")
        try:
            w.set_foreground()
        except:
            print("Had issues setting to foreground")
    def spawnCheckRespondingThread(self):
        thread = threading.Thread(target=self.CheckAndHandleNotResponding, args=())
        thread.daemon = True  # Daemonize thread
        thread.start()  # Start the execution

    def window_exists(self,window_name):
        try:
            win32ui.FindWindow(None, window_name)
            return True
        except win32ui.error:
            return False
    def CheckAndHandleNotResponding(self):
        while True:
            #Cheat engine might not be responding if it fails to attach debugger
            if(self.notresponding("DarkSoulsIII.exe") or self.window_exists("Error") or self.notresponding("cheatengine-x86_64.exe") or self.window_exists("Lua Engine")):
                with not_responding_lock:
                    self.releaseAll()
                    print("Game not responding, waiting 5 seconds until restart")
                    PressAndRelease(U)
                    time.sleep(5)
                    if (self.notresponding("DarkSoulsIII.exe")or self.window_exists("Error") or self.notresponding("cheatengine-x86_64.exe") or self.window_exists("Lua Engine")):
                        self.kill_processes()
                        os.system('".\\DarkSoulsIII.CT"')
                        time.sleep(5)
                        os.system('"'+DARKSOULSDIR+'"')
                        w=WindowMgr()
                        time.sleep(40)
                        PressAndRelease(T)
                        PressAndRelease(I)
                        w.find_window_wildcard(".*ARK SOULS.*")
                        iter=0
                        print("Spamming E to get into game",iter)
                        while iter<1000:
                            try:
                                w.set_foreground()
                            except:
                                print("Had issues setting to foreground")

                            PressAndFastRelease(E)
                            iter+=1
                            stateDict=self.readState()

                            if(stateDict[areaKey]==BONFIREAREA):
                                break #we are in game

                        time.sleep(5)
                        print("Assuming in game now")
                        PressAndRelease(T)
                        ReleaseKey(E)
            time.sleep(5)

    def teleToBoss(self):
        self.setDsInFocus()
        time.sleep(5)
        for i in range(50):
            self.waitForUnpause()
            self.check_responding_lock()
            PressAndRelease(F1)
            PressAndRelease(U)#Normal speed
            PressAndRelease(E)
            PressAndRelease(E)#Twice, bloodstain can be at entrance
            time.sleep(2)
            #Check whether we have entered boss area
            stateDict=self.readState()
            if(stateDict[areaKey]==BOSSAREA):
                PressAndRelease(F2)
                PressAndRelease(Q)
                PressAndFastRelease(T)
                break
            elif i%20:
                print("Tried 20 times, killing self and resetting boss")
                PressAndRelease(F3)
                time.sleep(20)

        else:   #For loop else, not if else
                #didn't get to boss area in many tries, commit sudoku and kill both processes
            PressAndRelease(F3)
            print("Couldn't get to boss in 50 tries, something wrong, killing processes as well")
            self.kill_processes()

    def kill_or_wait(self,start_read):
        elapsed = int(time.time() - start_read)
        max_wait_time = 30
        print("waiting for loading screen", elapsed, " of max", max_wait_time)
        if elapsed >= max_wait_time:
            self.kill_processes()
            # wait for restart thread to pick it up, then wait for lock
            time.sleep(10)
            self.check_responding_lock()
        else:
            time.sleep(1)

    def readState(self):
        hasRead=False
        start_read=time.time()

        while (hasRead==False):
            self.logfile.seek(0)
            try:
                loglines = self.logfile.readline()
            except:
                print("Couldn't read from file, will retry")
                continue
            if not loglines or len(loglines.split(";;"))<22:
                continue
            stateDict= {}
            for line in loglines.split(";;"):
                try:
                    (key,val) = line.split("::")
                    stateDict[key]=val
                except:
                    print("Had issues reading state, will try again")
                    break
            else:
                hasRead = True
        return stateDict
    def reset(self):
        self.setDsInFocus()
        self.releaseAll()
        self.waitForUnpause()
        self.teleToBoss()
        self.setDsInFocus()
        self.set_initial_state()
        return self.step(NO_ACTION)[0]

    def waitForUnpause(self):
        #Using Global Speed as a pause button (f7 and f8 in cheatengine)
        stateDict=self.readState()
        if stateDict["Global Speed"]=="0":
            self.releaseAll()
            print("Script paused as Global Speed is 0, waiting for unpause ....")
            while stateDict["Global Speed"]=="0":
                time.sleep(1)
                stateDict=self.readState()
            print("Global Speed is not 0 anymore, script is unpaused")

    def can_reset(self):
        self.releaseAll()
        stateDict=self.readState()
        #self.CheckAndHandleNotResponding()
        return stateDict[charHpKey] !=0

    def kill_processes(self):
        os.system("taskkill /f /im  DarkSoulsIII.exe /T")
        # also kill cheat engine
        os.system("taskkill /f /im  cheatengine-x86_64.exe /T")
    def check_responding_lock(self):
        not_responding_lock.acquire()
        not_responding_lock.release()

    def step(self,input_actions):
        terminal=False
        reward=0.0

        self.unpause_wrapper()
        #Check if able to take not responding lock

        self.check_responding_lock()

        self.ensure_framerate()
        stateDict = self.readState()
        #Check if we died
        if(stateDict[charHpKey]=="0" or stateDict[areaKey]==BONFIREAREA or stateDict[areaKey]=="??"):
            #Unpause game and wait for hp>0
            self.releaseAll()
            PressAndRelease(U)
            terminal=True
            reward=-1
        #Check if we killed the boss or missing boss into
        elif stateDict[bossHpKey]=="0" or stateDict[bossHpKey]=="??":
            self.releaseAll()
            if stateDict[bossHpKey]=="0":
                terminal=True
                print("killed boss")
                PressAndRelease(G)
                PressAndRelease(E)
                time.sleep(5)
                reward=1
            PressAndRelease(U)
            PressAndRelease(F3)

        #Check if lost target on boss
        elif stateDict["targetLock"]=="0":
            print("Lost target, retargeting until i die")
            while stateDict["targetLock"]=="0" and stateDict[charHpKey]!="0":
                self.releaseAll()
                PressAndFastRelease(Q)
                stateDict=self.readState()
        #Input action
        self.handleAction(input_actions)

        if stateDict[bossHpKey]!="??" and self.bossHpLastFrame>int(stateDict[bossHpKey]):
            hpdiff=self.bossHpLastFrame-int(stateDict[bossHpKey])
            reward+=(hpdiff/LUDEX_BASE_HP)*HEALTH_REWARD_MULTIPLIER
            self.timesincebosslosthp=0
        else:
            self.timesincebosslosthp = self.timesincebosslosthp+1
            if self.timesincebosslosthp > TIMESTEPS_DEFENSIVE_BEHAVIOR:
                print("Agent is playing too defensively, negative reward")
                reward -=DEFENSIVE_BEHAVIOR_NEGATIVE_REWARD

        #If our hp is different from last frame, can result in reward if char got healed
        if stateDict[charHpKey]!="??" and int(stateDict[charHpKey])!=int(self.charHpLastFrame):
            hpdiff=int(self.charHpLastFrame)-int(stateDict[charHpKey])
            reward-=hpdiff/HERO_BASE_HP
            self.timesinceherolosthp=0
        else:
            self.timesinceherolosthp+=1

        if self.bossAnimationLastFrame!=parryAnimationName and stateDict['targetAnimationName']==parryAnimationName:
            reward+=PARRY_REWARD
            print("Got reward for parrying, last animation: ", self.bossAnimationLastFrame, " current animation: ", stateDict['targetAnimationName'])
            self.timesinceheroparry=0
        else:
            self.timesinceheroparry+=1

        #Keep hero close to boss and incentivise being alive
        if self.calc_dist(stateDict) < REWARD_DISTANCE:
            reward+=0.001
        else:
            reward-=0.001

        #penalize using estus to prevent spam
        numEstus=self.parseStateDictValue(stateDict,"numEstus")
        if (self.numEstusLastFrame>numEstus):
            #penalize using estus to prevent spam
            #also prevents estus being used above ~80%life
            reward-=ESTUS_NEGATIVE_REWARD
        self.numEstusLastFrame=numEstus

        if stateDict[bossHpKey]!="??":
            self.bossHpLastFrame=int(stateDict[bossHpKey])
        if stateDict[charHpKey]!="??":
            self.charHpLastFrame=int(stateDict[charHpKey])

        if self.bossAnimationLastFrame == stateDict['targetAnimationName']:
            self.bossAnimationFrameCount+=1
        else:
            self.bossAnimationLastFrame=stateDict['targetAnimationName']
            if self.bossAnimationLastFrame in self.bossAnimationSet:
                self.prev_boss_animations.append(self.bossAnimationSet.index(self.bossAnimationLastFrame))
            else:
                self.bossAnimationSet.append(self.bossAnimationLastFrame)
                self.prev_boss_animations.append(self.bossAnimationSet.index(self.bossAnimationLastFrame))
                print(self.bossAnimationLastFrame,"did not exist in bossAnimationList, adding it")

            self.bossAnimationFrameCount=0

        if self.charAnimationLastFrame == stateDict['heroAnimationName']:
            self.charAnimationFrameCount+=1
        else:
            self.charAnimationLastFrame=stateDict['heroAnimationName']
            if self.charAnimationLastFrame in self.charAnimationSet:
                self.prev_char_animations.append(self.charAnimationSet.index(self.charAnimationLastFrame))
            else:
                self.charAnimationSet.append(self.charAnimationLastFrame)
                self.prev_char_animations.append(self.charAnimationSet.index(self.charAnimationLastFrame))
                print(stateDict['heroAnimationName'],"did not exist in heroAnimationList adding it")
            self.charAnimationFrameCount=0
        if "Attack" in stateDict['targetAnimationName']:
            self.timesincebossattack=0
        else:
            self.timesincebossattack+=1

        stateDict["reward"]=reward
        self.add_state(input_actions,stateDict)
        self.episode_len+=1
        self.episode_rew+=reward
        if terminal:
            self.releaseAll()
            self.info={'episode':{'r':self.episode_rew,'l':self.episode_len,'kill':stateDict[bossHpKey]=="0",'bosshp':self.bossHpLastFrame}}
            #Save shadowplay recording

            if(self.episode_rew>self.best_so_far and SAVE_PROGRESS_SHADOWPLAY):
                print("Saving shadowplay because of best ep rew>best so far")
                print("Episode rew:",self.episode_rew)
                print("Best episode rew:",self.best_so_far)
                PressAndFastRelease(F11)
                self.best_so_far=self.episode_rew
            if(stateDict[bossHpKey]=="0" and SAVE_KILLS_SHADOWPLAY):
                print("Saving shadowplay as boss was killed")
                PressAndFastRelease(F11)
            self.episode_rew=0
            self.episode_len=0
            self.fill_frame_buffer=True #Fill buffer next time, if we died
            PressAndRelease(I) #speed up when dead

        return np.hstack(self.prev_state), reward, terminal, self.info

    def releaseAll(self):
        ReleaseKeys([P,W,A,S,D,E,R,SPACE,NUM1,NUM2,NUM4])

    def handleAction(self,input_actions):
        self.releasePreviousActions(self.prev_input_actions,input_actions)
        if input_actions[0] == 1:
            PressKey(W)
        if input_actions[0] == 2:
            PressKey(A)
        if input_actions[0] == 3:
            PressKey(S)
        if input_actions[0] == 4:
            PressKey(D)
        if input_actions[1] == 1:
            PressKey(SPACE)
        if input_actions[1] == 2:
            self.timesincecharacterattack=0
            PressKey(NUM1)
        else:
            self.timesincecharacterattack+=1
        if input_actions[1] == 3:
            PressKey(NUM2)
        if input_actions[1] == 4:
            PressKey(NUM4)
        if input_actions[1] == 5:
            if self.numEstusLastFrame == 0:
                pass
            else:
                PressKey(R)
        self.prev_input_actions=input_actions

    def releasePreviousActions(self, prevaction, curaction):
        keys = []
        if prevaction[0] != curaction[0]:
            if prevaction[0] ==1:
                keys.append(W)
            if prevaction[0] ==2:
                keys.append(A)
            if prevaction[0] ==3:
                keys.append(S)
            if prevaction[0] ==4:
                keys.append(D)

        if prevaction[1] != curaction[1]:
            if prevaction[1] ==1:
                keys.append(SPACE)
            if prevaction[1] ==2:
                keys.append(NUM1)
            if prevaction[1] ==3:
                keys.append(NUM2)
            if prevaction[1] ==4:
                keys.append(NUM4)
            if prevaction[1] ==5:
                keys.append(R)
        ReleaseKeys(keys)

#Function makes it possible to hold key pressed, valuable for blocking or moving
    def releaseAllExcept(self, action):
        #Always release attack key and parry key. Holding attack key does not make sense
        keys=[P,E,NUM1,NUM4,R]

        if action[0] !=1:
            keys.append(W)
        if action[0] !=2:
            keys.append(A)
        if action[0] !=3:
            keys.append(S)
        if action[0] !=4:
            keys.append(D)
        if action[1] !=1:
            keys.append(SPACE)
        if action[1] !=2:
            keys.append(NUM1)
        if action[1] !=3:
            keys.append(NUM2)
        if action[1] !=4:
            keys.append(NUM4)

        ReleaseKeys(keys)

    def ensure_framerate(self):
        global start_time
         # Sleep to ensure consistency in frames
        if start_time != -1:
            elapsed = time.time() - start_time
            timeToSleep = FRAME_DIFF - elapsed
            if timeToSleep > 0:
                time.sleep(timeToSleep)
                #print("New elapsed ",time.time()-start_time)
            else:
                print("Didn't sleep")
        start_time = time.time()

    def parseStateDictValue(self,stateDict,key):
        if (stateDict[key]=="??" or stateDict[key]==""):
            return 0
        else:
            try:
                return float(stateDict[key].replace(",","."))
            except:
                print("Couldn't transform value to float for key: ",key, "using 0 instead")
                return 0
    def calc_dist(self,stateDict):
        targetx=self.parseStateDictValue(stateDict,"targetedEntityX")
        targety=self.parseStateDictValue(stateDict,"targetedEntityY")
        herox=self.parseStateDictValue(stateDict,"heroX")
        heroy=self.parseStateDictValue(stateDict,"heroY")
        return math.sqrt((targetx-herox)**2+(targety-heroy)**2)

    def print_state_dict(self,stateDict):
        _ = system('cls')
        for k in stateDict:
            print (k,stateDict[k])

    def save_state(self,save_path):
        with open(save_path+"envstate.pkl", "wb") as file_handler:
            objtosave={}
            objtosave["bossAnimation"]= self.bossAnimationSet
            objtosave["charAnimation"]= self.charAnimationSet
            pickle.dump(objtosave, file_handler)
    def load_state(self,load_path):
        with open(load_path.replace(".zip","envstate.pkl"), "rb") as file_handler:
            loadedobj = pickle.load(file_handler)
            self.bossAnimationSet=loadedobj["bossAnimation"]
            self.charAnimationSet=loadedobj["charAnimation"]
    def add_state(self,action_to_add,stateDict):
        targetX=self.parseStateDictValue(stateDict,"targetedEntityX")
        targetY=self.parseStateDictValue(stateDict,"targetedEntityY")
        heroX=self.parseStateDictValue(stateDict,"heroX")
        heroY=self.parseStateDictValue(stateDict,"heroY")

        stateToAdd=np.zeros(num_state_scalars)
        stateToAdd[action_to_add[0]]=1
        stateToAdd[action_to_add[1]+5]=1
        stateToAdd[12]=self.parseStateDictValue(stateDict,"targetedEntityHp")
        stateToAdd[13]=targetX
        stateToAdd[14]=targetY
        stateToAdd[15]=self.parseStateDictValue(stateDict,"targetedEntityZ")
        targetAngle=self.parseStateDictValue(stateDict,"targetedEntityAngle")
        stateToAdd[16]=targetAngle
        stateToAdd[17]=self.parseStateDictValue(stateDict,"targetAttack1")
        stateToAdd[18]=float(self.parseStateDictValue(stateDict,"targetAttack2"))
        stateToAdd[19]=self.parseStateDictValue(stateDict,"targetMovement1")
        stateToAdd[20]=self.parseStateDictValue(stateDict,"targetMovement2")
        stateToAdd[21]=self.parseStateDictValue(stateDict,"targetComboAttack")
        stateToAdd[22]=self.parseStateDictValue(stateDict,"heroHp")
        stateToAdd[23]=heroX
        stateToAdd[24]=heroY

        dist=self.calc_dist(stateDict)
        stateToAdd[25]=dist
        heroAngle=self.parseStateDictValue(stateDict,"heroAngle")
        stateToAdd[26]=heroAngle
        stateToAdd[27]=self.parseStateDictValue(stateDict,"heroSp")
        stateToAdd[28]=stateDict["reward"]
        stateToAdd[29]=stateDict["HeroAnimationCounter"]
        stateToAdd[30]=self.timesincecharacterattack
        stateToAdd[31]=self.timesincebossattack
        stateToAdd[32]=stateDict["BossAnimationCounter"]
        estus=self.parseStateDictValue(stateDict,"numEstus")
        stateToAdd[33]=estus
        if estus>0:
            stateToAdd[34]=1
        stateToAdd[35]=math.sin(heroAngle)
        stateToAdd[36]=math.cos(heroAngle)
        stateToAdd[37]=math.sin(targetAngle)
        stateToAdd[38]=math.cos(targetAngle)
        stateToAdd[39]=heroX-targetX
        stateToAdd[39]=heroY-targetY
        stateToAdd[40]=self.timesincebosslosthp
        stateToAdd[41]=stateDict["BossAnimationCounter"]
        stateToAdd[42]=stateDict["HeroAnimationCounter"]
        stateToAdd[43]=self.timesinceherolosthp
        stateToAdd[44]=self.timesinceheroparry
        charAnimationStartIndex=45
        #Allow for 100 char animations and 100 boss animations
        charAnimationLength=100
        bossAnimationStartIndex= charAnimationStartIndex+charAnimationLength

        #One hot encode prev and current animations
        #charAnimationIndex=charAnimationStartIndex+self.prev_char_animations[0]
        #stateToAdd[charAnimationIndex]=1
        #bossAnimationIndex=bossAnimationStartIndex+self.prev_boss_animations[0]
        #stateToAdd[bossAnimationIndex]=1
        #Allow for 128 char animations and 128 boss animations
        bossAnimationAsBinary = bin_array(self.prev_boss_animations[0],7)
        charAnimationAsBinary = bin_array(self.prev_char_animations[0],7)
        for i in range(7):
            stateToAdd[charAnimationStartIndex+i]=bossAnimationAsBinary[i]
        for i in range(7):
            stateToAdd[charAnimationStartIndex+7+i]=charAnimationAsBinary[i]

        if self.fill_frame_buffer:
            for _ in range(num_history_states):
                self.prev_state.append(stateToAdd)
            self.fill_frame_buffer = False
        else:
            self.prev_state.append(stateToAdd)

def bin_array(num, m):
    """Convert a positive integer num into an m-bit bit vector"""
    return np.array(list(np.binary_repr(num).zfill(m))).astype(np.int8)

reason: import numpy,from numpy