import time
from umodbus.tcp import TCP as ModbusTCPMaster
import network
from umqtt.simple import MQTTClient
# ===============================================
# connect to a network
station = network.WLAN(network.STA_IF)
if station.active() and station.isconnected():
    station.disconnect()
    time.sleep(1)
station.active(False)
time.sleep(1)
station.active(True)

# station.connect('SSID', 'PASSWORD')
station.connect('Fusion Automate', 'Fusion_Automate')
time.sleep(1)

while True:
    print('Waiting for WiFi connection...')
    if station.isconnected():
        print(f'Connected to WiFi, Pico W IP : {station.ifconfig()[0]}')
        break
    time.sleep(2)
# ===============================================
# Define MQTT Broker credentials
MQTT_BROKER_IP = '192.168.29.221'
MQTT_BROKER_PORT = 1883
MQTT_CLIENT_ID = 'Pico_W_Mqtt_Client'
MQTT_TOPIC = 'Pico_W/Modbus'
# ===============================================
# Define MQTT client
mqtt_client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER_IP, MQTT_BROKER_PORT,keepalive=30)
mqtt_client.connect()
# ===============================================
# TCP Slave setup
port = 502            # port to listen to
slave_addr = 1        # bus address of modbus_client
# IP Address of Modbus TCP Server
ip = '192.168.29.221'
# register_numbers = [0,2,4,6,8]
coil_numbers = [0,2,4,6,8]
# ===============================================
# Setup Modbus TCP Client
modbus_client = ModbusTCPMaster(slave_ip=ip,slave_port=port,timeout=5)
print(f'Requesting data from Modbus TCP Server at {ip}:{port}')
# ===============================================

while True:
    try:
        # for i in range(len(register_numbers)):
        #     register_value = modbus_client.read_holding_registers(slave_addr=slave_addr,starting_addr=register_numbers[i],register_qty=1)
        #     mqtt_client.publish(MQTT_TOPIC + '/HR/' + str(register_numbers[i]), str(register_value[0]))
        for i in range(len(coil_numbers)):
            coil_value = modbus_client.read_coils(slave_addr=slave_addr,starting_addr=coil_numbers[i],coil_qty=1)
            mqtt_client.publish(MQTT_TOPIC + '/COIL/' + str(coil_numbers[i]), str(coil_value[0]))
    except KeyboardInterrupt:
        mqtt_client.disconnect()
        print('KeyboardInterrupt, stopping TCP client...')
        break
    except Exception as e:
        print('Exception during execution: {}'.format(e))


import numpy as np
from scipy import signal
import cv2
import matplotlib.pyplot as plt
from gauss2D import gauss2D

def box_kernel(kernel_size):
    return np.ones((kernel_size, kernel_size)) / kernel_size**2

def filtering_image(image, kernel, n_channels):
    denoised_image = np.zeros_like(image)
    for channel in range(n_channels):
        denoised_image[:, :, channel] = signal.convolve2d(image[:, :, channel], kernel, mode='same')
    return denoised_image

def median_filtering(image, n_channels, kernel_size):
    pad_size = int(kernel_size/2)
    padded_image = np.pad(image, [(pad_size, pad_size), (pad_size, pad_size), (0, 0)], 'edge')
    denoised_image = np.zeros_like(image)

    for channel in range(n_channels):
        for i in range(int(kernel_size/2), image.shape[0]):
            for j in range(int(kernel_size/2), image.shape[1]):
                denoised_image[i, j, channel] = np.median(padded_image[i:i+kernel_size, j:j+kernel_size, channel])
    return denoised_image

def denoise(image, kernel_type, **kwargs):
    n_channels = image.shape[-1] if len(image.shape) > 2 else 1
    image = image.reshape(image.shape[0], image.shape[1], n_channels)

    if kernel_type == 'box':
        # kernel = box_kernel(**kwargs)
        # denoised_image = filtering_image(image, kernel, n_channels)
        denoised_image = cv2.blur(image, **kwargs)
    elif kernel_type == 'median':
        # denoised_image = median_filtering(image, n_channels, **kwargs)
        denoised_image = cv2.medianBlur(image, **kwargs)
    elif kernel_type == 'gaussian':
        kernel = gauss2D(**kwargs)
        denoised_image = filtering_image(image, kernel, n_channels)
    else:
        print('Operation not implemented')

    return denoised_image


"""
Decoder Only model
"""

import torch
import torch.nn as nn

from tmodels.decoder.config import DecoderOnlyConfig
from tmodels.decoder.layers import DecoderLayer, ModelBlock
from tmodels.vanilla_transformer.embeddings import Embeddings

class DecoderOnly(nn.Module):
    """
    Transformer model with Encoder and Decoder.
    Both Input and Output are transformed to embeddings with positional encoding.
    The next token prediction is done by a linear layer on the output of the decoder.
    """

    def __init__(
        self,
        config: DecoderOnlyConfig,
    ):
        super().__init__()
        self.d_seq = config.d_seq
        self.embedding = Embeddings(config.vocab_size, config)
        self.transformer = ModelBlock(config, DecoderLayer)

        self.linear = nn.Linear(config.d_embed, config.vocab_size)

    def forward(self, x):
        x = self.embedding(x)
        x = self.transformer(x)
        logits = self.linear(x)
        return logits

    def generate(self, x, max_len, do_sample=False, top_k=None, last_token=None):
        init_len = x.shape[-1]
        shifted = False
        for _ in range(max_len):
            logits = self(x)
            if top_k is not None:
                v, _ = torch.topk(logits, top_k)
                logits[logits < v[:, [-1]]] = -float("Inf")
            probs = torch.softmax(logits, dim=-1)
            if do_sample:
                idx_next = torch.multinomial(probs[:, -1, :], num_samples=1)
            else:
                _, idx_next = torch.topk(probs, k=1, dim=-1)
            x = torch.cat([x, idx_next], dim=-1)
            if shifted or idx_next == last_token:
                break
            if not shifted and x.shape[-1] > self.d_seq:
                x = x[:, 1:]
                shifted = True
        return x if shifted else x[:, 1:]

if __name__ == "__main__":
    config_ = DecoderOnlyConfig()
    model = DecoderOnly(config_)
    print(model)


import os.path as osp
import os
import numpy as np
from mindspore import Tensor, ops
import mindspore as ms
from scipy.spatial import cKDTree
from pytorch3d.structures import Meshes
from pytorch3d.renderer.mesh import rasterize_meshes
import torchvision
from PIL import Image, ImageFont, ImageDraw
# from kaolin.metrics.trianglemesh import point_to_mesh_distance
# from kaolin.ops.mesh import check_sign
import torch

from iconlib.common.render_utils import Pytorch3dRasterizer, face_vertices

class SMPLX:
    """SMPL model"""
    def __init__(self):
        self.current_dir = osp.join(osp.dirname(__file__), "../../data/smpl_related")

        self.smpl_verts_path = osp.join(self.current_dir, "smpl_data/smpl_verts.npy")
        self.smplx_verts_path = osp.join(self.current_dir, "smpl_data/smplx_verts.npy")
        self.faces_path = osp.join(self.current_dir, "smpl_data/smplx_faces.npy")
        self.cmap_vert_path = osp.join(self.current_dir, "smpl_data/smplx_cmap.npy")

        self.faces = np.load(self.faces_path)
        self.verts = np.load(self.smplx_verts_path)
        self.smpl_verts = np.load(self.smpl_verts_path)

        self.model_dir = osp.join(self.current_dir, "models")
        self.tedra_dir = osp.join(self.current_dir, "../tedra_data")

    def get_smpl_mat(self, vert_ids):
        """get smpl model mat"""
        mat = Tensor(np.load(self.cmap_vert_path), dtype=ms.float32)
        return mat[vert_ids, :]

    def smpl2smplx(self, vert_ids=None):
        """convert vert_ids in smpl to vert_ids in smplx

        Args:
            vert_ids ([int.array]): [n, knn_num]
        """
        smplx_tree = cKDTree(self.verts, leafsize=1)
        _, ind = smplx_tree.query(self.smpl_verts, k=1)  # ind: [smpl_num, 1]

        if vert_ids is not None:
            smplx_vert_ids = ind[vert_ids]
        else:
            smplx_vert_ids = ind

        return smplx_vert_ids

    def smplx2smpl(self, vert_ids=None):
        """convert vert_ids in smplx to vert_ids in smpl

        Args:
            vert_ids ([int.array]): [n, knn_num]
        """
        smpl_tree = cKDTree(self.smpl_verts, leafsize=1)
        _, ind = smpl_tree.query(self.verts, k=1)  # ind: [smplx_num, 1]
        if vert_ids is not None:
            smpl_vert_ids = ind[vert_ids]
        else:
            smpl_vert_ids = ind

        return smpl_vert_ids

def get_visibility(xy, z, faces):
    """get the visibility of vertices

    Args:
        xy (torch.tensor): [N,2]
        z (torch.tensor): [N,1]
        faces (torch.tensor): [N,3]
        size (int): resolution of rendered image
    """

    xyz = torch.cat((xy, -z), dim=1)
    xyz = (xyz + 1.0) / 2.0
    faces = faces.long()

    rasterizer = Pytorch3dRasterizer(image_size=2 ** 12)
    meshes_screen = Meshes(verts=xyz[None, ...], faces=faces[None, ...])
    raster_settings = rasterizer.raster_settings

    pix_to_face = rasterize_meshes(
        meshes_screen,
        image_size=raster_settings.image_size,
        blur_radius=raster_settings.blur_radius,
        faces_per_pixel=raster_settings.faces_per_pixel,
        bin_size=raster_settings.bin_size,
        max_faces_per_bin=raster_settings.max_faces_per_bin,
        perspective_correct=raster_settings.perspective_correct,
        cull_backfaces=raster_settings.cull_backfaces,
    )

    vis_vertices_id = torch.unique(faces[torch.unique(pix_to_face), :])
    vis_mask = torch.zeros(size=(z.shape[0], 1))
    vis_mask[vis_vertices_id] = 1.0

    # print("------------------------\n")
    # print(f"keep points : {vis_mask.sum()/len(vis_mask)}")

    return vis_mask

def get_optim_grid_image(per_loop_lst, loss=None, nrow=4, type_p="smpl"):
    """get optimized grid image"""
    font_path = os.path.join(os.path.dirname(__file__), "tbfo.ttf")
    print(font_path)
    font = ImageFont.truetype(font_path, 30)
    grid_img = torchvision.utils.make_grid(torch.cat(per_loop_lst, dim=0), nrow=nrow)
    grid_img = Image.fromarray(
        ((grid_img.permute(1, 2, 0).detach().cpu().numpy() + 1.0) * 0.5 * 255.0).astype(
            np.uint8
        )
    )

    # add text
    draw = ImageDraw.Draw(grid_img)
    grid_size = 512
    if loss is not None:
        draw.text((10, 5), f"error: {loss:.3f}", (255, 0, 0), font=font)

    if type_p == "smpl":
        for col_id, col_txt in enumerate(
                ["image", "smpl-norm(render)", "cloth-norm(pred)", "diff-norm", "diff-mask"]
        ):
            draw.text((10 + (col_id * grid_size), 5), col_txt, (255, 0, 0), font=font)
    elif type_p == "cloth":
        for col_id, col_txt in enumerate(
                ["image", "cloth-norm(recon)", "cloth-norm(pred)", "diff-norm"]
        ):
            draw.text((10 + (col_id * grid_size), 5), col_txt, (255, 0, 0), font=font)
        for col_id, col_txt in enumerate(["0", "90", "180", "270"]):
            draw.text(
                (10 + (col_id * grid_size), grid_size * 2 + 5),
                col_txt,
                (255, 0, 0),
                font=font,
            )
    else:
        print(f"{type_p} should be 'smpl' or 'cloth'")

    grid_img = grid_img.resize((grid_img.size[0], grid_img.size[1]), Image.ANTIALIAS)

    return grid_img

def orthogonal(points, calibrations, transforms=None):
    """
    Compute the orthogonal projections of 3D points into the image plane by given projection matrix
    :param points: [B, 3, N] Tensor of 3D points
    :param calibrations: [B, 3, 4] Tensor of projection matrix
    :param transforms: [B, 2, 3] Tensor of image transform matrix
    :return: xyz: [B, 3, N] Tensor of xyz coordinates in the image plane
    """
    rot = calibrations[:, :3, :3]
    trans = calibrations[:, :3, 3:4]
    pts = torch.baddbmm(trans, rot, points)  # [B, 3, N]
    if transforms is not None:
        scale = transforms[:2, :2]
        shift = transforms[:2, 2:3]
        pts[:, :2, :] = torch.baddbmm(shift, scale, pts[:, :2, :])
    return pts

def cal_sdf_batch(verts, faces, cmaps, vis, points):
    """calculate sdf batch"""
    # verts [B, N_vert, 3]
    # faces [B, N_face, 3]
    # triangles [B, N_face, 3, 3]
    # points [B, N_point, 3]
    # cmaps [B, N_vert, 3]

    b_size = points.shape[0]

    normals = Meshes(verts, faces).verts_normals_padded()

    triangles = face_vertices(verts, faces)
    normals = face_vertices(normals, faces)
    cmaps = face_vertices(cmaps, faces)
    vis = face_vertices(vis, faces)

    residues, pts_ind, _ = point_to_mesh_distance(points, triangles)
    closest_triangles = torch.gather(
        triangles, 1, pts_ind[:, :, None, None].expand(-1, -1, 3, 3)
    ).view(-1, 3, 3)
    closest_normals = torch.gather(
        normals, 1, pts_ind[:, :, None, None].expand(-1, -1, 3, 3)
    ).view(-1, 3, 3)
    closest_cmaps = torch.gather(
        cmaps, 1, pts_ind[:, :, None, None].expand(-1, -1, 3, 3)
    ).view(-1, 3, 3)
    closest_vis = torch.gather(
        vis, 1, pts_ind[:, :, None, None].expand(-1, -1, 3, 1)
    ).view(-1, 3, 1)
    bary_weights = barycentric_coordinates_of_projection(
        points.view(-1, 3), closest_triangles
    )

    pts_cmap = (closest_cmaps * bary_weights[:, :, None]).sum(1).unsqueeze(0)
    pts_vis = (closest_vis * bary_weights[:, :, None]).sum(1).unsqueeze(0).ge(1e-1)
    pts_norm = (closest_normals * bary_weights[:, :, None]).sum(1).unsqueeze(
        0
    ) * torch.tensor([-1.0, 1.0, -1.0]).type_as(normals)
    pts_dist = torch.sqrt(residues) / torch.sqrt(torch.tensor(3))

    pts_signs = 2.0 * (check_sign(verts, faces[0], points).float() - 0.5)
    pts_sdf = (pts_dist * pts_signs).unsqueeze(-1)

    return (
        pts_sdf.view(b_size, -1, 1),
        pts_norm.view(b_size, -1, 3),
        pts_cmap.view(b_size, -1, 3),
        pts_vis.view(b_size, -1, 1),
    )

def barycentric_coordinates_of_projection(points, vertices):
    """
    https://github.com/MPI-IS/mesh/blob/master/mesh/geometry/barycentric_coordinates_of_projection.py

    Given a point, gives projected coords of that point to a triangle
    in barycentric coordinates.

    See
        **Heidrich**, Computing the Barycentric Coordinates of a Projected Point, JGT 05
        at http://www.cs.ubc.ca/~heidrich/Papers/JGT.05.pdf

    :param p: point to project. [B, 3]
    :param v0: first vertex of triangles. [B, 3]
    :returns: barycentric coordinates of ``p``'s projection in triangle defined
     by ``q``, ``u``, ``v``
            vectorized so ``p``, ``q``, ``u``, ``v`` can all be ``3xN``
    """
    # (p, q, u, v)
    v_0, v_1, v_2 = vertices[:, 0], vertices[:, 1], vertices[:, 2]
    p_p = points

    q_p = v_0
    u_p = v_1 - v_0
    v_p = v_2 - v_0
    n_p = torch.cross(u_p, v_p)
    s_p = torch.sum(n_p * n_p, dim=1)
    # If the triangle edges are collinear, cross-product is zero,
    # which makes "s" 0, which gives us divide by zero. So we
    # make the arbitrary choice to set s to epsv (=numpy.spacing(1)),
    # the closest thing to zero
    s_p[s_p == 0] = 1e-6
    one_over_4a_squared = 1.0 / s_p
    w_p = p_p - q_p
    b_2 = torch.sum(torch.cross(u_p, w_p) * n_p, dim=1) * one_over_4a_squared
    b_1 = torch.sum(torch.cross(w_p, v_p) * n_p, dim=1) * one_over_4a_squared
    weights = torch.stack((1 - b_1 - b_2, b_1, b_2), dim=-1)
    # check barycenric weights
    # p_n = v0*weights[:,0:1] + v1*weights[:,1:2] + v2*weights[:,2:3]
    return weights

def feat_select(feat, select):
    """feat select"""
    # feat [B, featx2, N]
    # select [B, 1, N]
    # return [B, feat, N]

    dim = feat.shape[1] // 2
    idx = ops.tile((1 - select), (1, dim, 1)) * dim + ops.expand_dims(
        ops.expand_dims(ms.numpy.arange(0, dim), axis=0), axis=2
    ).astype(select.dtype)
    return ops.gather_elements(feat, 1, idx.astype(ms.int64))


import numpy as np
import pandas as pd
import datetime

city = 'Orange'
start_time, end_time = '2022-01-01 00:00', '2022-01-28 23:59'  # 数据下载开始于结束时间
time_str = start_time[2:10] + '_' + end_time[2:10]

save_path = r'./%s/' % city  # 文件保存路径
vds_list = np.genfromtxt(save_path + "%s_mainline.txt" % city, dtype=int)  # 需要下载的VDS列表
save_path = save_path + time_str + '/'

def dataInterval(incident):
    start = datetime.datetime.strptime(incident['Start Time'], '%m-%d-%y %H:%M')
    duration = datetime.timedelta(minutes=int(incident['Duration (mins)']))
    end = start + duration

    incident['Start Time'] = (start.day - 1) * 24 * 60 / 5 + start.hour * 60 / 5 + int(start.minute / 5)
    incident['End Time'] = (end.day - 1) * 24 * 60 / 5 + end.hour * 60 / 5 + int(end.minute / 5)
    return incident

def pre_process_incident(path=save_path):
    incident = pd.read_excel(path + 'incident.xlsx', index_col=None)
    incident = incident.drop(columns=['Incident Id', 'Source', 'AREA', 'LOCATION', 'DESCRIPTION'])

    incident = incident.apply(dataInterval, axis=1)
    incident = incident.drop(columns=['Duration (mins)', 'CA PM'])
    incident = incident.loc[:, ['Start Time', 'End Time', 'Freeway', 'Abs PM']]

    incident = incident.groupby('Freeway')
    for (name, data) in incident:
        data = data.drop(columns='Freeway')
        data.to_excel(path + '%s.xlsx' % name, index=None)
    print('incident preprocess succeed!')
    return

def create_incident_npz(path=save_path):
    print('start create incident.npz')
    info = pd.read_excel('./%s/%s.xlsx' % (city, city), index_col=None)
    info = info[info.Type.isin(['Mainline'])]
    info = info.drop(
        columns=['District', 'County', 'City', 'CA PM', 'Length', 'Name', 'Lanes', 'Sensor Type', 'HOV', 'MS ID',
                 'IRM', 'Type'])

    data = np.zeros([len(vds_list), int(4 * 7 * 24 * 60 / 5), 1], dtype=np.float64)

    for (Fwy, sensor) in info.groupby('Fwy'):
        incident = pd.read_excel(path + '%s.xlsx' % Fwy, index_col=None, names=None)
        for row in incident.itertuples():
            Abs_PM = getattr(row, '_3')
            if Fwy[-1] == 'N' or Fwy[-1] == 'E':
                sensor['len'] = sensor['Abs PM'].apply(lambda x: x - Abs_PM)
            elif Fwy[-1] == 'S' or Fwy[-1] == 'W':
                sensor['len'] = sensor['Abs PM'].apply(lambda x: Abs_PM - x)
            if len(sensor[sensor.len >= 0]) > 0:
                idx = sensor[sensor.len >= 0]['len'].argmin()
            else:
                idx = sensor['len'].argmax()

            # idx = sensor_tmp['len'].argmin()
            id = int((sensor['ID'].iloc[[idx]].values)[0])

            id_idx = (np.argwhere(vds_list == id))[0][0]
            data[id_idx][getattr(row, '_1'):getattr(row, '_2')] = 1
        # print(sensor)
    data = np.transpose(data, [1, 0, 2])
    print(data.shape)
    np.savez(path + 'incident.npz', data=data)
    print('create incident.npz succeed!')
    return

if __name__ == '__main__':
    # pre_process_incident(save_path + 'incident/')
    create_incident_npz(save_path + 'incident/')
    # print(np.argwhere(data == True))


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if head==None:
            return head
        tail=head
        length=1
        while tail.next:
            length+=1
            tail=tail.next
        k=k%length
        if k==0:
            return head
        tail.next=head
        ptr=head
        for i in range(length-k-1):
            ptr=ptr.next
        head=ptr.next
        ptr.next=None
        return head


"""
    EXTERNAL LIBRARIES
"""

import sys
import numpy as np
import random
import matplotlib.pyplot as plt
import math

"""
    INTERNAL UTIL LIBRARIES
"""

from PerceptronLearningAlgorithm import PerceptronLearningNetwork
# Add parent directory to the sys path
sys.path.append('../')
# Import any python modules from parent directory
from utils.auxfunctions import plotModel

"""
    Adaline (adaptive linear neuron) networks are a single-layer network
    with a step function as the nonlinearity. Although the perceptron was
    analyzed assuming binary inputs, Adaline inputs may be continuous.

    Weights are adjusted with thhe Widrow-Hoff learning rule to minimize
    the difference between the output and externally supplied target.

    the Widrow-Hoff learning rule, also called the LMS algorithm or the
    delta rule, is basically an iterative implementation of linear
    regression. Both minimize the mean squared error of a linear fit.
"""

class AdalineNetwork(PerceptronLearningNetwork):

    def __init__(self, numInputs, numOutputs, randomize=False, bias=False):
        """
            Construct a single-layer neural network given the number of input
            nodes and the number of output nodes. This network will train
            using the Widrow-Hoff learning rule. The activation function
            used in this network will be a linear threshold unit where
            y = -1 if u <= 0
            y = +1 if u > 0     where u is the output of the weighted sum of inputs

            Input, output, and target values are assumed to be +- 1
        """
        super().__init__(numInputs, numOutputs, randomize, bias)
        self.iterations = 0

    def getOutputNoActivation(self, inputs):
        """
            Evaluate the inputs passing through the neural network using the
            network's current weights. Do not pass the outputs through the
            activation function.
        """
        if self.bias:
            inputs = np.concatenate((inputs, np.ones((inputs.shape[0], 1))), axis=1)
        self.outputNodes = np.dot(inputs, self.weights.T)
        return self.outputNodes

    def train(self, x, y, epochs=1, verbose=False):
        """
            Train the network given a batch of inputs, x, and their corresponding
            target outputs, y. Run the perceptron learning algorithm on the training
            set for the number of times specified by the epochs parameter.

            The error is reduced by a factor of lr each time the weights are updated.
            Stability requires that 0 < lr < 2 and generally 0.1 < lr < 1.0. For lr=1,
            the error on the present pattern is completely corrected in one cycle;
            for lr > 1, it is overcorrected.

            If the input patterns are linearly independent, the weights will converge
            to unique values. If not, the corrections will be oscillatory and lr should
            decrease over time to allow the weights to settle. One possible schedule is
            lr = k^-1, where k indexes the iterations.
        """
        numTrainingPoints = len(x)
        for e in range(epochs):
            # Set accuracy at beginning of epochs to 0s
            accuracy = 0
            # Compute the output for all training points
            allOutputs = self.getOutputNoActivation(x)
            for i in range(numTrainingPoints):
                # Increment iterations for learning rate scheduling
                self.iterations += 1
                # Calculate the new learning rate from scheduling
                lr = self.iterations ** -1
                # Grab the input for the specific training point
                trainingPointInputs = x[i]
                # Grab the output for the specific training point
                trainingPointOutput = allOutputs[i]
                # Get the target outputs for the specific training point
                targets = y[i]
                # Compare each output 1 by 1
                for outputIndex in range(len(trainingPointOutput)):
                    # Grab specific output and corresponding target value
                    targetVal = targets[outputIndex]
                    outputVal = trainingPointOutput[outputIndex]
                    # If the outputs match, increment accuracy
                    if targetVal == outputVal:
                        accuracy += 1
                        continue
                    # Else, update the weights
                    else:
                        # For each input weight, compute its delta change, and then apply the change
                        for inputWeightIndex in range(len(self.weights[outputIndex])):
                            # If the inputWeightIndex is in the range of values for inputs, use the input at that index
                            if inputWeightIndex < len(trainingPointInputs):
                                trainingPointInput = trainingPointInputs[inputWeightIndex]
                            # Else, that value is the bias, and the input should be constant 1.0
                            else:
                                trainingPointInput = 1.0
                            # Compute delta w and apply the change
                            inputNorm = 0
                            for tpi in trainingPointInputs:
                                inputNorm += tpi ** 2
                            inputNorm = math.sqrt(inputNorm)
                            deltaW = lr * (targetVal - outputVal) * trainingPointInput / inputNorm**2
                            self.weights[outputIndex, inputWeightIndex] += deltaW
            # Compute accuracy
            accuracy /= numTrainingPoints
            # If verbose == True, print accuuracy for each training epoch
            if verbose:
                print('Epoch ' + str(e+1) + ' / ' + str(epochs) + ' Accuracy: ' + str(accuracy))
            # Return final accuracy
        return accuracy

# Test the network's learning capabilities
if __name__ == '__main__':
    """
        Test the network on the AND and XOR Boolean functions. Show training progress
        in graphs.
    """
    # Params
    EPOCHS = 20
    NUM_GRAPHS = 10

    NUM_EPOCHS_PER_GRAPH = math.ceil(EPOCHS / NUM_GRAPHS)
    # Create AND training data
    and_train_x = np.array([
        [-1, -1],
        [-1, 1],
        [1, -1],
        [1, 1]
    ])
    and_train_y = np.array([
        [-1],
        [-1],
        [-1],
        [1]
    ])
    # Create XOR training data
    xor_train_x = np.array([
        [-1, -1],
        [-1, 1],
        [1, -1],
        [1, 1]
    ])
    xor_train_y = np.array([
        [-1],
        [1],
        [1],
        [-1]
    ])
    # Create networks
    and_aln = AdalineNetwork(2, 1, randomize=True, bias=True)
    xor_aln = AdalineNetwork(2, 1, randomize=True, bias=True)

    # Create the suplots
    fig, axes = plt.subplots(2, NUM_GRAPHS)
    fig.suptitle('Adaline Network Training on AND and XOR Boolean Functions',
                 fontsize=18)

    # Label the subplots
    for x in range(2):
        for y in range(1, NUM_GRAPHS+1):
            if x == 0:
                axes[x][y-1].set_title('XOR Model at\n' + str(y * int(NUM_EPOCHS_PER_GRAPH)) + ' Epochs')
            else:
                axes[x][y-1].set_title('AND Model at\n' + str(y * int(NUM_EPOCHS_PER_GRAPH)) + ' Epochs')

    # Train each model on their respective datasets and show progress in the form
    # of decision boundaries for every N epochs
    for i in range(NUM_GRAPHS):
        # Train each model for N more epochs
        xor_aln.train(xor_train_x, xor_train_y, epochs=NUM_EPOCHS_PER_GRAPH, verbose=False)
        and_aln.train(and_train_x, and_train_y, epochs=NUM_EPOCHS_PER_GRAPH, verbose=False)

        # Plot the model
        plotModel(xor_aln, axes[0, i], [-1.2, 1.2, -1.2, 1.2], [-1.0, 1.0])
        axes[0, i].set_xlim(-1.2, 1.2)
        axes[0, i].set_ylim(-1.2, 1.2)
        axes[0, i].set_aspect('equal', adjustable='box')

        plotModel(and_aln, axes[1, i], [-1.2, 1.2, -1.2, 1.2], [-1.0, 1.0])
        axes[1, i].set_xlim(-1.2, 1.2)
        axes[1, i].set_ylim(-1.2, 1.2)
        axes[1, i].set_aspect('equal', adjustable='box')

        # Plot the actual data for each model
        axes[0, i].scatter([-1, 1], [1, -1], c='blue', s=150)
        axes[0, i].scatter([-1, 1], [-1, 1], c='red', s=150)

        axes[1, i].scatter([1], [1], c='blue', s=150)
        axes[1, i].scatter([-1, -1, 1], [-1, 1, -1], c='red', s=150)

    # Plot the graph
    figManager = plt.get_current_fig_manager()
    figManager.window.showMaximized()
    plt.show()

    """
        14 of the 16 Boolean functions are linearly separable.
        Let's show all of them and how Adaline networks perform when using the
        Widrow-Hoff Learning Rule.
    """
    # Params
    EPOCHS_PER_MODEL = 50

    # Define class to hold info about each Boolean function
    class BooleanFunction:
        def __init__(self, true_x, false_x, name):
            self.true_x = true_x
            self.false_x = false_x
            self.name = name

        def getTrainingData(self):
            training_x = []
            training_y = []
            for pair in self.true_x:
                training_x.append(pair)
                training_y.append([1])
            for pair in self.false_x:
                training_x.append(pair)
                training_y.append([-1])
            return np.array(training_x), np.array(training_y)

    # Define each of the 16 boolean functions
    functions = []
    functions.append(
        BooleanFunction(
            [],
            [[-1, -1], [-1, 1], [1, -1], [1,1]],
            'FALSE'
        )
    )
    functions.append(
        BooleanFunction(
            [[1, 1]],
            [[-1, -1], [-1, 1], [1, -1]],
            'AND'
        )
    )
    functions.append(
        BooleanFunction(
            [[1, -1]],
            [[-1, -1], [-1, 1], [1, 1]],
            'A AND NOT B'
        )
    )
    functions.append(
        BooleanFunction(
            [[1, -1], [1, 1]],
            [[-1, -1], [-1, 1]],
            'A'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, 1]],
            [[-1, -1], [1, -1], [1, 1]],
            'NOT A AND B'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, 1], [1, 1]],
            [[-1, -1], [1, -1]],
            'B'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, 1], [1, -1]],
            [[-1, -1], [1, 1]],
            'XOR'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, 1], [1, -1], [1, 1]],
            [[-1, -1]],
            'OR'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, -1]],
            [[-1, 1], [1, -1], [1, 1]],
            'NOR'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, -1], [1, 1]],
            [[-1, 1], [1, -1]],
            'XNOR'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, -1], [1, -1]],
            [[-1, 1], [1, 1]],
            'NOT B'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, -1], [1, -1], [1, 1]],
            [[-1, 1]],
            'A OR NOT B'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, -1], [-1, 1]],
            [[1, -1], [1, 1]],
            'NOT A'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, -1], [-1, 1], [1, 1]],
            [[1, -1]],
            'NOT A OR B'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, -1], [-1, 1], [1, -1]],
            [[1, 1]],
            'NAND'
        )
    )
    functions.append(
        BooleanFunction(
            [[-1, -1], [-1, 1], [1, -1], [1, 1]],
            [],
            'TRUE'
        )
    )

    # Create the pyplot
    fig, axes = plt.subplots(2, 8)
    fig.suptitle('14 of 16 Boolean functions are linearly separable.\n' +
                'These graphs display decision boundaries formed by training\n' +
                'Adaline Networks using Widrow-Hoff Learning Rule.',
                fontsize=14)

    # Print out a warning to user that this may take a while, but progress will be output below
    print('\n\nWARNING: This may take a while. Progress will be output below:\n\n')

    # Create models for each of the functions, and plot the trained models
    f, x, y = 0, 0, 0
    for function in functions:
        # Create Single Layer Network
        model = AdalineNetwork(2, 1, randomize=True, bias=True)

        # Train the model on its dataset
        training_x, training_y = function.getTrainingData()
        model.train(training_x, training_y, epochs=EPOCHS_PER_MODEL, verbose=False)

        # Print progress
        print('PROGRESS: ' + str(f+1) + ' / 16')

        # Plot the trained model in the appropriate subplot
        plotModel(model, axes[x, y], [-1.2, 1.2, -1.2, 1.2], valRange=[-1.0, 1.0])
        axes[x, y].set_xlim(-1.2, 1.2)
        axes[x, y].set_ylim(-1.2, 1.2)
        axes[x, y].set_aspect('equal', adjustable='box')
        axes[x, y].set_title(function.name)

        # Plot the points in the dataset
        for pair in function.true_x:
            axes[x, y].scatter(pair[0], pair[1], color='blue', s=150)
        for pair in function.false_x:
            axes[x, y].scatter(pair[0], pair[1], color='red', s=150)

        # Increment the trackers
        f += 1
        x += 1
        if x >= 2:
            x = 0
            y += 1

    # Set caption
    textstr = str('Notice how the Adaline networks learn the separating boundary\n' +
                  'that minimizes the MSE for the dataset (except XOR and XNOR which\n' +
                  'are non-linear). The network converges on the best unique value\n' +
                  'to classify these functions.')
    props = dict(boxstyle='round', facecolor='wheat', alpha=1.0)
    plt.text(-15, 2.5, textstr, fontsize=14, bbox=props)

    # Plot the graph
    figManager = plt.get_current_fig_manager()
    figManager.window.showMaximized()
    plt.show()

    """
        Adaline networks work with continuous inputs as well. Let's create
        a random clustered dataset and see how well the Adaline network classifies this data.
    """
    # Params
    EPOCHS = 20
    NUM_GRAPHS = 5

    NUM_POINTS_PER_CLASS = 40
    NOISE = 4

    NUM_EPOCHS_PER_GRAPH = math.ceil(EPOCHS / NUM_GRAPHS)

    # Create the training data
    train_x = []
    train_y = []

    classOneLine = (1, -2)
    classTwoLine = (5, 3)

    xvalues = []
    classOneY = []
    classTwoY = []

    for _ in range(NUM_POINTS_PER_CLASS):
        x = random.random() * 10
        y1 = classOneLine[0] * x + classOneLine[1] + (random.random()-0.5) * 2.0 * NOISE
        y2 = classTwoLine[0] * x + classTwoLine[1] + (random.random()-0.5) * 2.0 * NOISE

        xvalues.append(x)
        classOneY.append(y1)
        classTwoY.append(y2)

        train_x.append([x, y1])
        train_y.append([-1])

        train_x.append([x, y2])
        train_y.append([1])

    train_x = np.asarray(train_x)
    train_y = np.asarray(train_y)

    # Create the network
    adaline = AdalineNetwork(2, 1, randomize=False, bias=True)

    # Create the subplots
    fig, axes = plt.subplots(1, NUM_GRAPHS)
    fig.suptitle('Adaline Network training on randomized dataset\n' +
                 'with continuous values, and a learnable (but not completely\n' +
                 'linearly separable) rule.',
                 fontsize=14)

    # Label the subplots
    for y in range(1, NUM_GRAPHS+1):
        axes[y-1].set_title('Adaline Network at\n' + str(y * int(NUM_EPOCHS_PER_GRAPH)) + ' Epochs')

    # Train each model on their respective datasets and show progress in the form
    # of decision boundaries for every N epochs
    for i in range(NUM_GRAPHS):
        # Train the model for N more epochs
        adaline.train(train_x, train_y, epochs=NUM_EPOCHS_PER_GRAPH, verbose=False)

        # Plot the model
        plotModel(adaline, axes[i], [-10.2, 20.0, -10.2, 20.0], [-1.0, 1.0], steppingSize=0.1)
        axes[i].set_xlim(-10.2, 20.0)
        axes[i].set_ylim(-10.2, 20.0)
        axes[i].set_aspect('equal', adjustable='box')

        # Plot the actual data for the model
        axes[i].scatter(xvalues, classOneY, c='red', s=50)
        axes[i].scatter(xvalues, classTwoY, c='blue', s=50)

    # Plot the graph
    figManager = plt.get_current_fig_manager()
    figManager.window.showMaximized()
    plt.show()

3. Single-Layer Networks/3.4 Learning Rules for Single-Layer Networks/AdalineNetworks.py


from flask import (
    Flask,
    Blueprint,
    send_file,
    render_template,
    abort
)

from autoswatch.image import Image
from autoswatch.utils import validate_hex_color

routes = Blueprint('autoswatch', __name__)

@routes.route('/')
def root():
    return render_template('index.j2')

@routes.route('/hex/<hex_color>')
def value_only(hex_color):
    color = validate_hex_color(hex_color)
    if not color['valid']:
        return abort(400)

    buffer = Image(color=color['value']).byte_stream()
    return send_file(buffer, mimetype='image/png')


import peewee
import datetime

db = peewee.SqliteDatabase('test.db')

class Note(peewee.Model):

    text = peewee.CharField()
    created = peewee.DateField(default=datetime.date.today)

    class Meta:

        database = db
        db_table = 'notes'

# There are two ways to select a single instance; each of them uses a get() method.
# First
note1 = Note.select().where(Note.text == 'Went to cinema').get()

print(note1.id)
print(note1.text)
print(note1.created)

# Second
note2 = Note.get(Note.text == 'Listened to music')

print(note2.id)
print(note2.text)
print(note2.created)


import os
import csv

file_name = "Main_PyBank"

csvpath = os.path.join("..", "..", "Resources", "budget_data.csv")
with open(csvpath) as csvfile:

    csvreader = csv.reader(csvfile,delimiter=',')

    Months = 0
    Profits_Losses = 0

    rows = [r for r in csvreader]

    Change_Profits_Losses = int(rows[1][1])
    max = rows[1]
    min = rows[1]

    for i in range(1,len(rows)):

        Months = Months+1
        row = rows[i]
        Profits_Losses = int(row[1]) + Profits_Losses

        if i > 1:
            Change_Profits_Losses = Change_Profits_Losses + int(row[1])-int(rows[i-1][1])
        if int(max[1]) < int(row[1]):
            max = row
        if int(min[1]) > int(row[1]):
            min = row

Average= int(Profits_Losses /Months)

print("Total Months:                         " + str(Months))
print("Total Profits:                        " +"$" +str(Profits_Losses))
print("Average Change in Profits/Losses:     " +"$"+ str(Average))
print("Greatest Increase in Profits:         " + str(max[0])+" ($" + str(max[1])+")")
print("Greatest Decrease in Profits:         " + str(min[0])+" ($" + str(min[1])+")")

save_file = file_name.strip(".csv") + ".txt"
filepath = os.path.join(".", save_file)
with open(filepath,'w') as text:

    text.write("Total Months:                         " + str(Months) + "\n")
    text.write("Total Profits:                        " +"$" +str(Profits_Losses) + "\n")
    text.write("Average Change in Profits/Losses:     " +"$"+ str(Average) + "\n")
    text.write("Greatest Increase in Profits:         " + str(max[0])+" ($" + str(max[1])+")" + "\n")
    text.write("Greatest Decrease in Profits:         " + str(min[0])+" ($" + str(min[1])+")" + "\n")


import pandas as pd
import requests
import os
print(os.path.exists("image"))

if not os.path.exists("image"):
    os.mkdir("image")
    df = pd.read_csv("node.csv")

    image_names = []

    for i, url in enumerate(df["Image"].tolist()):
        img_data = requests.get(url).content

        image_name = '{}.jpg'.format(i)
        image_names.append(image_name)
        with open("image/{}".format(image_name), 'wb') as handler:
            handler.write(img_data)

    df["Image"] = image_names
    df.to_csv("new_node.csv", index=False)


"""
Iterable validators for array objects only. They provide a way of
applying a schema to any given items in an array.
"""
from notario.exceptions import Invalid, SchemaError
from notario.engine import IterableValidator
from notario.utils import is_callable, safe_repr, expand_schema, is_schema

class BasicIterableValidator(object):
    """
    Base class for iterable validators, can be sub-classed
    for other type of iterable validators but should not be
    used directly.
    """

    __validator_leaf__ = True

    def __init__(self, schema):
        self.schema = schema

    def safe_type(self, data, tree):
        """
        Make sure that the incoming data complies with the class type we
        are expecting it to be. In this case, classes that inherit from this
        base class expect data to be of type ``list``.
        """
        if not isinstance(data, list):
            name = self.__class__.__name__
            msg = "did not pass validation against callable: %s" % name
            reason = 'expected a list but got %s' % safe_repr(data)
            raise Invalid(self.schema, tree, reason=reason, pair='value', msg=msg)

class AnyItem(BasicIterableValidator):
    """
    Go over all the items in an array and make sure that at least
    one of the items validates correctly against the schema provided.
    If no items pass it raises ``Invalid``.

    .. note::
        It only works on arrays, otherwise it will raise a ``SchemaError``

    .. testsetup::

        from notario import validate
        from notario.validators.iterables import AnyItem

    Example usage for single values::

        data = {'foo' : [10, 30, 50]}
        schema = ('foo', AnyItem(50))
        validate(data, schema)

    Example usage for other data structures::

        data = {'foo': [{'a': 1}, {'b': 2}]}
        schema = ('foo', AnyItem(('b', 2))
        validate(data, schema)

    When a single item in the array matches correctly against the validator's
    schema it stops further iteration and the validation passes. Otherwise it
    will raise an error like:

    .. doctest::

        >>> data = {'foo': [{'a': 1}, {'b': 2}]}
        >>> schema = ('foo', AnyItem(('c', 4)))
        >>> validate(data, schema)
        Traceback (most recent call last):
        ...
        Invalid: -> foo -> list[]  did not contain any valid items matching ('c', 4)

    """

    def __call__(self, data, tree):
        schema = expand_schema(self.schema)
        self.safe_type(data, tree)
        index = len(data) - 1
        validator = IterableValidator(data, schema, [], index=index, name='AnyItem')
        for item_index in range(len(data)):
            try:
                return validator.leaf(item_index)
            except Invalid:
                pass

        tree.append('list[]')
        if is_callable(schema):
            msg = "did not contain any valid items against callable: %s" % schema.__name__
        else:
            msg = "did not contain any valid items matching %s" % repr(schema)
        raise Invalid(schema, tree, pair='value', msg=msg)

class AllItems(BasicIterableValidator):
    """
    For all the items in an array apply the schema passed in to the validator.
    If a single item fails, it raises ``Invalid``.

    .. note::
        It only works on arrays, otherwise it will raise a ``SchemaError``

    .. testsetup:: allitems

        from notario import validate
        from notario.validators.iterables import AllItems

    Example usage for single values::

        data = {'foo' : [10, 10, 10]}
        schema = ('foo', AllItems(10))
        validate(data, schema)

    Example usage for other data structures::

        data = {'foo': [{'a': 1}, {'a': 1}]}
        schema = ('foo', AllItems(('a', 1))
        validate(data, schema)

    When a single item in the array fails to pass against the validator's
    schema it stops further iteration and it will raise an error like:

    .. doctest:: allitems

        >>> data = {'foo': [{'a': 1}, {'a': 2}]}
        >>> schema = ('foo', AllItems(('a', 1)))
        >>> validate(data, schema)
        Traceback (most recent call last):
        ...
        Invalid: -> foo -> list[1] -> a -> 2  did not match 1

    In this particular validator, it remembers on what index of the array the
    failure was created and it goes even further giving the key and value of
    the object it went against.

    """

    def __call__(self, data, tree):
        schema = expand_schema(self.schema)
        self.safe_type(data, tree)
        validator = IterableValidator(data, schema, tree, name='AllItems')
        validator.validate()

class MultiIterable(object):

    """
    .. testsetup:: *

        from notario import validate
        from notario.validators.iterables import MultiIterable

    This validator is useful when there is a need for validating any number of
    schemas for a given data set.

    If the requirement is, for example, to validate either ``string: string``
    or ``string: int`` this will not be possible with any of the other
    validators in Notario because they all assume a rule that must dominate
    everything. Otherwise, it is required to specify the expectation.

    In the case that the object to validate complies with the above
    requirement, this validator can accept **any number** of schemas as
    arguments, so if one schema fails, the next one will be tried until all the
    schemas are applied for a given item. The ``MultiRecursive`` validator will
    look like this in order to pass the incoming data:

    .. doctest:: multiiterable

        >>> data = {'main': {'foo': 'bar'}}
        >>> schema = ('main', MultiIterable(('foo', 1), ('foo', 'bar')))
        >>> validate(data, schema)

    Because we can't be sure what the data may hold we are forced to define
    different rules and apply them so that they can pass. If we repeat the
    expectation but an invalid value comes along, the validator will naturally
    fail:

    .. doctest:: mutlirecursive_fail

        >>> data = {'main': [{'foo': False}]}
        >>> schema = ('main', MultiIterable(('foo', 1), ('foo', 'bar')))
        >>> validate(data, schema)
        Traceback (most recent call last):
        ...
        Invalid: -> foo -> False did not match 'bar'

    """
    __validator_leaf__ = True

    def __init__(self, *schemas):
        for schema in schemas:
            if not is_schema(schema):
                raise TypeError("got a non schema argument: %s" % safe_repr(schema))
        self.schemas = schemas

    def __call__(self, data, tree):
        """
        Go through each item in data against the first schema in the arguments.
        If that fails try each subsequent schema until it passes. Even if
        schemas are failing to apply to that given item, consume all the
        available ones until at least one passes.

        If nothing passes, the last error is raised.

        :param data: Incoming data from the validator engine in normalized dict
        form.
        :param tree: The traversing tree up to this point, always passed in.
        :raises Invalid: If none of the schemas can validate the data.
        """
        first_schema = expand_schema(self.schemas[0])
        index = len(data) - 1
        validator = IterableValidator(data, first_schema, tree, index=index, name='MultiIterable')

        for item_index in range(len(data)):
            try:
                validator.leaf(item_index)
            except (SchemaError, Invalid):
                self.itemized_validation(validator, item_index)

    def itemized_validation(self, validator, item_index):
        error = None

        for schema in self.schemas:
            try:
                validator.schema = expand_schema(schema)
                validator.tree = []
                return validator.leaf(item_index)
            except (SchemaError, Invalid) as e:
                error = e

        if error is not None:
            raise error


"""Route declaration."""
#system imports
from flask import Blueprint, render_template, request
from app import db
load_dp = Blueprint('load',__name__, url_prefix='/load', template_folder='templates',static_folder='static')

#nav List
nav = [
    {'name': 'Home', 'url': '/'},
    {'name': 'Prealgebra', 'url': '/prealgebra'},
    {'name': 'Algebra', 'url': '/algebra'},
    {'name': 'Load', 'url': '/loadwkst'},
    {'name': 'Contact', 'url': '/contact'}
    #{'name': 'Signup', 'url': '/signup'}
]

@load_dp.route('/')
def load_main():
    cur = db.connection.cursor()
    cur.execute("SELECT title FROM mmtseed WHERE sname LIKE 'jaegeun'")
    title = cur.fetchall()

    #cur.execute("SELECT desc FROM mmtseed WHERE sname LIKE 'jaegeun'")
    #desc = cur.fetchall()

    cur.execute("SELECT sname FROM mmtseed WHERE sname LIKE 'jaegeun'")
    sname = cur.fetchall()

    cur.execute("SELECT tname FROM mmtseed WHERE sname LIKE 'jaegeun'")
    tname = cur.fetchall()

    cur.execute("SELECT seed FROM mmtseed WHERE sname LIKE 'jaegeun'")
    seed = cur.fetchall()

    arr = [title, sname, tname, seed]
    print(arr)

    return render_template(
        'load/load.html',
        descripstion = 'load worksheet',
        darr = arr
        )


import functools
import threading
import typing

from python_util.logger.logger import LoggerFacade

CallableT = typing.TypeVar('CallableT', bound=typing.Callable)
LockId = str

class LockStripingLocks:
    def __init__(self):
        self.locks: dict[LockId, threading.RLock] = {}

def synchronized_lock_striping(locks: LockStripingLocks, lock_arg_arg_name: str):
    def outside_wrapper(function):

        @functools.wraps(function)
        def wrapper(self, *args, **kwargs):
            lock_id = kwargs[lock_arg_arg_name]
            if lock_id not in locks.locks.keys():
                LoggerFacade.info(f"Creating new lock with id {locks}.")
                locks.locks[lock_id] = threading.RLock()
            with locks.locks[lock_id]:
                return function(self, *args, **kwargs)

        return wrapper

    return outside_wrapper


# * coding: utf8 *
import numpy as np
import matplotlib.pyplot as plt

class PolyFit:
    def __init__(self, order, path='./data.txt'):
        # 多项式阶数
        self.order = order
        # 多项式模型参数 (y=w0+w1*x+w2*x^2+w3*x^3+...) @Model
        self.w = np.zeros(order + 1).reshape(order + 1, 1)
        # 从文件读取数据 @BigData
        data = np.loadtxt(path)
        # 待拟合点个数
        self.m = len(data)
        # 自变量
        self.x = np.array(data[:, 0]).reshape(self.m, 1)
        self.x = np.hstack((np.ones((self.m, 1)), self.x))
        # 因变量
        self.y = np.array(data[:, 1]).reshape(self.m, 1)
        # 学习率
        self.alpha = 0.01

    # 损失函数 @Loss
    # 均方误差
    def loss_function(self):
        mse = 0
        for i in range(0, self.m):
            v = np.polyval(self.w[::-1], self.x[i])
            mse += (self.y[i] - v) ** 2
        return mse / (2 * self.m)

    # 计算梯度
    def gradient_function(self):
        diff = np.dot(self.x, self.w) - self.y
        return np.dot(np.transpose(self.x), diff) / self.m

    # 梯度下降 @Algorithm
    def gradient_descent(self):
        gradient = self.gradient_function()
        while not np.all(np.absolute(gradient) <= 1e-5):
            self.w = self.w - self.alpha * gradient
            gradient = self.gradient_function()

if __name__ == '__main__':
    my_fit = PolyFit(1, './data.txt')
    my_fit.gradient_descent()
    plt.scatter(my_fit.x[:, 1], my_fit.y)
    print(my_fit.w)
    func = np.poly1d(np.array([my_fit.w[1, 0], my_fit.w[0, 0]]).astype(float))
    x = np.linspace(-5, 10, 10)
    y = func(x)
    plt.plot(x, y)
    plt.xlabel('X')
    plt.ylabel('y')
    plt.title('PolyFit Result')
    plt.show()


from zope.interface import Interface
from bika.lims.interfaces import IBikaLIMS

class ILayer(IBikaLIMS):
    """Layer Interface
    """

class ISenaiteImpressLayer(ILayer):
    """Senaite Impress Browser Layer Interface
    """

class IPublishView(Interface):
    """Publish View
    """

class IReportView(Interface):
    """Single Report View
    """

class IMultiReportView(Interface):
    """Multi Report View
    """

class IPublisher(Interface):
    """HTML -> PDF Publishing Engine
    """

class ITemplateFinder(Interface):
    """Utility to find template resources
    """

class IPdfReportStorage(Interface):
    """Storage adapter for report PDFs
    """

    def store(pdf, html, uids, metadata):
        """Stores the generated PDF for the given UIDs in a location and
        returns a list of generated report objects.
        """