# Once for All: Train One Network and Specialize it for Efficient Deployment
# Han Cai, Chuang Gan, Tianzhe Wang, Zhekai Zhang, Song Han
# International Conference on Learning Representations (ICLR), 2020.

import torch.nn as nn
import random
import time
import torch
import torch.nn.functional as F
from tqdm import tqdm

from ofa.utils import AverageMeter, cross_entropy_loss_with_soft_target
from ofa.utils import (
    DistributedMetric,
    list_mean,
    subset_mean,
    val2list,
    MyRandomResizedCrop,
)
from ofa.imagenet_classification.run_manager import DistributedRunManager

__all__ = [
    "validate",
    "train_one_epoch",
    "train",
    "load_models",
    "train_elastic_depth",
    "train_elastic_expand",
    "train_elastic_width_mult",
]

def validate(
    run_manager,
    epoch=0,
    is_test=False,
    image_size_list=None,
    ks_list=None,
    expand_ratio_list=None,
    depth_list=None,
    width_mult_list=None,
    additional_setting=None,
):
    dynamic_net = run_manager.net
    if isinstance(dynamic_net, nn.DataParallel):
        dynamic_net = dynamic_net.module

    dynamic_net.eval()

    if image_size_list is None:
        image_size_list = val2list(run_manager.run_config.data_provider.image_size, 1)
    if ks_list is None:
        ks_list = dynamic_net.ks_list
    if expand_ratio_list is None:
        expand_ratio_list = dynamic_net.expand_ratio_list
    if depth_list is None:
        depth_list = dynamic_net.depth_list
    if width_mult_list is None:
        if "width_mult_list" in dynamic_net.__dict__:
            width_mult_list = list(range(len(dynamic_net.width_mult_list)))
        else:
            width_mult_list = [0]

    subnet_settings = []
    for d in depth_list:
        for e in expand_ratio_list:
            for k in ks_list:
                for w in width_mult_list:
                    for img_size in image_size_list:
                        subnet_settings.append(
                            [
                                {
                                    "image_size": img_size,
                                    "d": d,
                                    "e": e,
                                    "ks": k,
                                    "w": w,
                                },
                                "R%s-D%s-E%s-K%s-W%s" % (img_size, d, e, k, w),
                            ]
                        )
    if additional_setting is not None:
        subnet_settings += additional_setting

    losses_of_subnets, top1_of_subnets, top5_of_subnets = [], [], []

    valid_log = ""
    for setting, name in subnet_settings:
        run_manager.write_log(
            "-" * 30 + " Validate %s " % name + "-" * 30, "train", should_print=False
        )
        run_manager.run_config.data_provider.assign_active_img_size(
            setting.pop("image_size")
        )
        dynamic_net.set_active_subnet(**setting)
        run_manager.write_log(dynamic_net.module_str, "train", should_print=False)

        run_manager.reset_running_statistics(dynamic_net)
        loss, (top1, top5) = run_manager.validate(
            epoch=epoch, is_test=is_test, run_str=name, net=dynamic_net
        )
        losses_of_subnets.append(loss)
        top1_of_subnets.append(top1)
        top5_of_subnets.append(top5)
        valid_log += "%s (%.3f), " % (name, top1)

    return (
        list_mean(losses_of_subnets),
        list_mean(top1_of_subnets),
        list_mean(top5_of_subnets),
        valid_log,
    )

def train_one_epoch(run_manager, args, epoch, warmup_epochs=0, warmup_lr=0):
    dynamic_net = run_manager.network
    distributed = isinstance(run_manager, DistributedRunManager)

    # switch to train mode
    dynamic_net.train()
    if distributed:
        run_manager.run_config.train_loader.sampler.set_epoch(epoch)
    MyRandomResizedCrop.EPOCH = epoch

    nBatch = len(run_manager.run_config.train_loader)

    data_time = AverageMeter()
    losses = DistributedMetric("train_loss") if distributed else AverageMeter()
    metric_dict = run_manager.get_metric_dict()

    with tqdm(
        total=nBatch,
        desc="Train Epoch #{}".format(epoch + 1),
        disable=distributed and not run_manager.is_root,
    ) as t:
        end = time.time()
        for i, (images, labels) in enumerate(run_manager.run_config.train_loader):
            MyRandomResizedCrop.BATCH = i
            data_time.update(time.time() - end)
            if epoch < warmup_epochs:
                new_lr = run_manager.run_config.warmup_adjust_learning_rate(
                    run_manager.optimizer,
                    warmup_epochs * nBatch,
                    nBatch,
                    epoch,
                    i,
                    warmup_lr,
                )
            else:
                new_lr = run_manager.run_config.adjust_learning_rate(
                    run_manager.optimizer, epoch - warmup_epochs, i, nBatch
                )

            images, labels = images.cuda(), labels.cuda()
            target = labels

            # soft target
            if args.kd_ratio > 0:
                args.teacher_model.train()
                with torch.no_grad():
                    soft_logits = args.teacher_model(images).detach()
                    soft_label = F.softmax(soft_logits, dim=1)

            # clean gradients
            dynamic_net.zero_grad()

            loss_of_subnets = []
            # compute output
            subnet_str = ""
            for _ in range(args.dynamic_batch_size):
                # set random seed before sampling
                subnet_seed = int("%d%.3d%.3d" % (epoch * nBatch + i, _, 0))
                random.seed(subnet_seed)
                subnet_settings = dynamic_net.sample_active_subnet()
                subnet_str += (
                    "%d: " % _
                    + ",".join(
                        [
                            "%s_%s"
                            % (
                                key,
                                "%.1f" % subset_mean(val, 0)
                                if isinstance(val, list)
                                else val,
                            )
                            for key, val in subnet_settings.items()
                        ]
                    )
                    + " || "
                )

                output = run_manager.net(images)
                if args.kd_ratio == 0:
                    loss = run_manager.train_criterion(output, labels)
                    loss_type = "ce"
                else:
                    if args.kd_type == "ce":
                        kd_loss = cross_entropy_loss_with_soft_target(
                            output, soft_label
                        )
                    else:
                        kd_loss = F.mse_loss(output, soft_logits)
                    loss = args.kd_ratio * kd_loss + run_manager.train_criterion(
                        output, labels
                    )
                    loss_type = "%.1fkd-%s & ce" % (args.kd_ratio, args.kd_type)

                # measure accuracy and record loss
                loss_of_subnets.append(loss)
                run_manager.update_metric(metric_dict, output, target)

                loss.backward()
            run_manager.optimizer.step()

            losses.update(list_mean(loss_of_subnets), images.size(0))

            t.set_postfix(
                {
                    "loss": losses.avg.item(),
                    **run_manager.get_metric_vals(metric_dict, return_dict=True),
                    "R": images.size(2),
                    "lr": new_lr,
                    "loss_type": loss_type,
                    "seed": str(subnet_seed),
                    "str": subnet_str,
                    "data_time": data_time.avg,
                }
            )
            t.update(1)
            end = time.time()
    return losses.avg.item(), run_manager.get_metric_vals(metric_dict)

def train(run_manager, args, validate_func=None):
    distributed = isinstance(run_manager, DistributedRunManager)
    if validate_func is None:
        validate_func = validate

    for epoch in range(
        run_manager.start_epoch, run_manager.run_config.n_epochs + args.warmup_epochs
    ):
        train_loss, (train_top1, train_top5) = train_one_epoch(
            run_manager, args, epoch, args.warmup_epochs, args.warmup_lr
        )

        if (epoch + 1) % args.validation_frequency == 0:
            val_loss, val_acc, val_acc5, _val_log = validate_func(
                run_manager, epoch=epoch, is_test=False
            )
            # best_acc
            is_best = val_acc > run_manager.best_acc
            run_manager.best_acc = max(run_manager.best_acc, val_acc)
            if not distributed or run_manager.is_root:
                val_log = (
                    "Valid [{0}/{1}] loss={2:.3f}, top-1={3:.3f} ({4:.3f})".format(
                        epoch + 1 - args.warmup_epochs,
                        run_manager.run_config.n_epochs,
                        val_loss,
                        val_acc,
                        run_manager.best_acc,
                    )
                )
                val_log += ", Train top-1 {top1:.3f}, Train loss {loss:.3f}\t".format(
                    top1=train_top1, loss=train_loss
                )
                val_log += _val_log
                run_manager.write_log(val_log, "valid", should_print=False)

                run_manager.save_model(
                    {
                        "epoch": epoch,
                        "best_acc": run_manager.best_acc,
                        "optimizer": run_manager.optimizer.state_dict(),
                        "state_dict": run_manager.network.state_dict(),
                    },
                    is_best=is_best,
                )

def load_models(run_manager, dynamic_net, model_path=None):
    # specify init path
    init = torch.load(model_path, map_location="cpu")["state_dict"]
    dynamic_net.load_state_dict(init)
    run_manager.write_log("Loaded init from %s" % model_path, "valid")

def train_elastic_depth(train_func, run_manager, args, validate_func_dict):
    dynamic_net = run_manager.net
    if isinstance(dynamic_net, nn.DataParallel):
        dynamic_net = dynamic_net.module

    depth_stage_list = dynamic_net.depth_list.copy()
    depth_stage_list.sort(reverse=True)
    n_stages = len(depth_stage_list) - 1
    current_stage = n_stages - 1

    # load pretrained models
    if run_manager.start_epoch == 0 and not args.resume:
        validate_func_dict["depth_list"] = sorted(dynamic_net.depth_list)

        load_models(run_manager, dynamic_net, model_path=args.ofa_checkpoint_path)
        # validate after loading weights
        run_manager.write_log(
            "%.3f\t%.3f\t%.3f\t%s"
            % validate(run_manager, is_test=True, **validate_func_dict),
            "valid",
        )
    else:
        assert args.resume

    run_manager.write_log(
        "-" * 30
        + "Supporting Elastic Depth: %s -> %s"
        % (depth_stage_list[: current_stage + 1], depth_stage_list[: current_stage + 2])
        + "-" * 30,
        "valid",
    )
    # add depth list constraints
    if (
        len(set(dynamic_net.ks_list)) == 1
        and len(set(dynamic_net.expand_ratio_list)) == 1
    ):
        validate_func_dict["depth_list"] = depth_stage_list
    else:
        validate_func_dict["depth_list"] = sorted(
            {min(depth_stage_list), max(depth_stage_list)}
        )

    # train
    train_func(
        run_manager,
        args,
        lambda _run_manager, epoch, is_test: validate(
            _run_manager, epoch, is_test, **validate_func_dict
        ),
    )

def train_elastic_expand(train_func, run_manager, args, validate_func_dict):
    dynamic_net = run_manager.net
    if isinstance(dynamic_net, nn.DataParallel):
        dynamic_net = dynamic_net.module

    expand_stage_list = dynamic_net.expand_ratio_list.copy()
    expand_stage_list.sort(reverse=True)
    n_stages = len(expand_stage_list) - 1
    current_stage = n_stages - 1

    # load pretrained models
    if run_manager.start_epoch == 0 and not args.resume:
        validate_func_dict["expand_ratio_list"] = sorted(dynamic_net.expand_ratio_list)

        load_models(run_manager, dynamic_net, model_path=args.ofa_checkpoint_path)
        dynamic_net.re_organize_middle_weights(expand_ratio_stage=current_stage)
        run_manager.write_log(
            "%.3f\t%.3f\t%.3f\t%s"
            % validate(run_manager, is_test=True, **validate_func_dict),
            "valid",
        )
    else:
        assert args.resume

    run_manager.write_log(
        "-" * 30
        + "Supporting Elastic Expand Ratio: %s -> %s"
        % (
            expand_stage_list[: current_stage + 1],
            expand_stage_list[: current_stage + 2],
        )
        + "-" * 30,
        "valid",
    )
    if len(set(dynamic_net.ks_list)) == 1 and len(set(dynamic_net.depth_list)) == 1:
        validate_func_dict["expand_ratio_list"] = expand_stage_list
    else:
        validate_func_dict["expand_ratio_list"] = sorted(
            {min(expand_stage_list), max(expand_stage_list)}
        )

    # train
    train_func(
        run_manager,
        args,
        lambda _run_manager, epoch, is_test: validate(
            _run_manager, epoch, is_test, **validate_func_dict
        ),
    )

def train_elastic_width_mult(train_func, run_manager, args, validate_func_dict):
    dynamic_net = run_manager.net
    if isinstance(dynamic_net, nn.DataParallel):
        dynamic_net = dynamic_net.module

    width_stage_list = dynamic_net.width_mult_list.copy()
    width_stage_list.sort(reverse=True)
    n_stages = len(width_stage_list) - 1
    current_stage = n_stages - 1

    if run_manager.start_epoch == 0 and not args.resume:
        load_models(run_manager, dynamic_net, model_path=args.ofa_checkpoint_path)
        if current_stage == 0:
            dynamic_net.re_organize_middle_weights(
                expand_ratio_stage=len(dynamic_net.expand_ratio_list) - 1
            )
            run_manager.write_log(
                "reorganize_middle_weights (expand_ratio_stage=%d)"
                % (len(dynamic_net.expand_ratio_list) - 1),
                "valid",
            )
            try:
                dynamic_net.re_organize_outer_weights()
                run_manager.write_log("reorganize_outer_weights", "valid")
            except Exception:
                pass
        run_manager.write_log(
            "%.3f\t%.3f\t%.3f\t%s"
            % validate(run_manager, is_test=True, **validate_func_dict),
            "valid",
        )
    else:
        assert args.resume

    run_manager.write_log(
        "-" * 30
        + "Supporting Elastic Width Mult: %s -> %s"
        % (width_stage_list[: current_stage + 1], width_stage_list[: current_stage + 2])
        + "-" * 30,
        "valid",
    )
    validate_func_dict["width_mult_list"] = sorted({0, len(width_stage_list) - 1})

    # train
    train_func(
        run_manager,
        args,
        lambda _run_manager, epoch, is_test: validate(
            _run_manager, epoch, is_test, **validate_func_dict
        ),
    )


import numpy as np
import sympy

import pytest

from devito import VectorFunction, TensorFunction, VectorTimeFunction, TensorTimeFunction
from devito import Grid, Function, TimeFunction, Dimension, Eq, div, grad
from devito.types import NODE

def dimify(dimensions):
    assert isinstance(dimensions, str)
    return tuple(Dimension(name=i) for i in dimensions.split())

@pytest.mark.parametrize('func_type, ndim', [
    (TensorFunction, 2), (TensorFunction, 3),
    (TensorTimeFunction, 2), (TensorTimeFunction, 3)])
def test_tensor_staggering(func_type, ndim):
    grid = Grid(tuple([5]*ndim))
    f = func_type(name="f", grid=grid)

    dims = grid.dimensions
    assert np.all(f[i, i].staggered == NODE for i in range(ndim))
    assert np.all(f[i, j].staggered == (dims[i], dims[j])
                  for i in range(ndim) for j in range(ndim) if i != j)

@pytest.mark.parametrize('func_type, ndim, sym', [
    (TensorFunction, 2, 'noop'), (TensorFunction, 3, 'noop'),
    (TensorFunction, 2, 'diag'), (TensorFunction, 3, 'diag'),
    (TensorFunction, 2, 'symm'), (TensorFunction, 3, 'symm'),
    (TensorTimeFunction, 2, 'noop'), (TensorTimeFunction, 3, 'noop'),
    (TensorTimeFunction, 2, 'diag'), (TensorTimeFunction, 3, 'diag'),
    (TensorTimeFunction, 2, 'symm'), (TensorTimeFunction, 3, 'symm')])
def test_tensor_symmetries(func_type, ndim, sym):
    grid = Grid(tuple([5]*ndim))
    f = func_type(name="f", grid=grid, symmetric=(sym == 'symm'),
                  diagonal=(sym == 'diag'))
    if sym == 'symm':
        assert np.all(f[i, j] == f[j, i] for i in range(ndim) for j in range(ndim))
    if sym == 'diag':
        assert np.all(f[i, j] == 0 for i in range(ndim) for j in range(ndim) if i != j)
    if sym == 'noop':
        assert np.all(f[i, j] != f[j, i] for i in range(ndim) for j in range(ndim))
        assert np.all(f[i, j] != 0 for i in range(ndim) for j in range(ndim) if i != j)

@pytest.mark.parametrize('func_type, ndim', [
    (VectorFunction, 2), (VectorFunction, 3),
    (VectorTimeFunction, 2), (VectorTimeFunction, 3)])
def test_vector_staggering(func_type, ndim):
    grid = Grid(tuple([5]*ndim))
    f = func_type(name="f", grid=grid)
    dims = grid.dimensions
    assert np.all(f[i].staggered == dims[i] for i in range(ndim))

@pytest.mark.parametrize('func_type, ndim', [
    (TensorFunction, 2), (TensorFunction, 3),
    (TensorTimeFunction, 2), (TensorTimeFunction, 3),
    (VectorFunction, 2), (VectorFunction, 3),
    (VectorTimeFunction, 2), (VectorTimeFunction, 3)])
def test_tensor_grid(func_type, ndim):
    grid = Grid(tuple([5]*ndim))
    f = func_type(name="f", grid=grid)
    assert np.all(ff.grid == grid for ff in f)

@pytest.mark.parametrize('func_type, ndim', [
    (TensorFunction, 2), (TensorFunction, 3),
    (TensorTimeFunction, 2), (TensorTimeFunction, 3),
    (VectorFunction, 2), (VectorFunction, 3),
    (VectorTimeFunction, 2), (VectorTimeFunction, 3)])
def test_tensor_space_order(func_type, ndim):
    grid = Grid(tuple([5]*ndim))
    f = func_type(name="f", grid=grid, space_order=10)
    assert np.all(ff.space_order == 10 for ff in f)

@pytest.mark.parametrize('func1, func2, out_type', [
    (Function, VectorFunction, VectorFunction),
    (Function, VectorTimeFunction, VectorTimeFunction),
    (TimeFunction, VectorTimeFunction, VectorTimeFunction),
    (Function, TensorFunction, TensorFunction),
    (Function, TensorTimeFunction, TensorTimeFunction),
    (TimeFunction, TensorTimeFunction, TensorTimeFunction),
    (TensorFunction, VectorFunction, VectorFunction),
    (TensorFunction, VectorTimeFunction, VectorTimeFunction),
    (TensorTimeFunction, VectorFunction, VectorTimeFunction),
    (TensorTimeFunction, VectorTimeFunction, VectorTimeFunction),
    (TensorTimeFunction, TensorFunction, TensorTimeFunction),
    (TensorTimeFunction, VectorTimeFunction, TensorTimeFunction)])
def test_tensor_matmul(func1, func2, out_type):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)
    f2 = func2(name="f2", grid=grid)
    assert isinstance(f1*f2, out_type)

@pytest.mark.parametrize('func1, func2, out_type', [
    (VectorFunction, TensorFunction, VectorFunction),
    (VectorTimeFunction, TensorFunction, VectorTimeFunction),
    (VectorFunction, TensorTimeFunction, VectorTimeFunction),
    (VectorTimeFunction, TensorTimeFunction, VectorTimeFunction)])
def test_tensor_matmul_T(func1, func2, out_type):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)
    f2 = func2(name="f2", grid=grid)
    assert isinstance(f1.T*f2, out_type)

@pytest.mark.parametrize('func1, func2, out_type', [
    (VectorFunction, VectorFunction, TensorFunction),
    (VectorTimeFunction, VectorTimeFunction, TensorTimeFunction),
    (VectorFunction, VectorTimeFunction, TensorTimeFunction)])
def test_tensor_outer(func1, func2, out_type):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)
    f2 = func2(name="f2", grid=grid)
    assert isinstance(f1*f2.T, out_type)

@pytest.mark.parametrize('func1', [TensorFunction, TensorTimeFunction,
                                   VectorFunction, VectorTimeFunction])
def test_tensor_custom_dims(func1):
    dimensions = dimify('i j k')
    ndim = 3
    f = func1(name="f", dimensions=dimensions, shape=(2, 3, 4))
    assert np.all(f[i, i].staggered == NODE for i in range(ndim))
    assert np.all(f[i, j].staggered == (dimensions[i], dimensions[j])
                  for i in range(3) for j in range(3) if i != j)

@pytest.mark.parametrize('func1', [TensorFunction, TensorTimeFunction])
def test_tensor_transpose(func1):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid, symmetric=False)
    f2 = f1.T
    assert np.all([f1[i, j] == f2[j, i] for i in range(3) for j in range(3)])

@pytest.mark.parametrize('func1', [VectorFunction, VectorTimeFunction])
def test_vector_transpose(func1):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)
    f2 = f1.T
    assert f2.shape == f1.shape[::-1]
    assert np.all([f1[i] == f2[i] for i in range(3)])

@pytest.mark.parametrize('func1', [VectorFunction, VectorTimeFunction])
def test_vector_transpose_deriv(func1):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)
    f2 = f1.dx.T
    assert all([f2[i] == f1[i].dx.T for i in range(3)])

@pytest.mark.parametrize('func1', [TensorFunction, TensorTimeFunction])
def test_tensor_transpose_deriv(func1):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)
    f2 = f1.dx.T
    assert np.all([f2[i, j] == f1[j, i].dx.T for i in range(3) for j in range(3)])

@pytest.mark.parametrize('func1', [TensorFunction, TensorTimeFunction,
                                   VectorFunction, VectorTimeFunction])
def test_transpose_vs_T(func1):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)
    f2 = f1.dx.T
    f3 = f1.dx.transpose(inner=True)
    f4 = f1.dx.transpose(inner=False)
    # inner=True is the same as T
    assert f3 == f2
    # inner=False doesn't tranpose inner derivatives
    for f4i, f2i in zip(f4, f2):
        assert f4i == f2i.T

@pytest.mark.parametrize('func1', [TensorFunction, TensorTimeFunction,
                                   VectorFunction, VectorTimeFunction])
def test_tensor_fd(func1):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)
    assert np.all([f.dx == f2 for f, f2 in zip(f1, f1.dx)])

@pytest.mark.parametrize('func1, symm, diag, expected',
                         [(TensorFunction, False, False, 9),
                          (TensorFunction, True, False, 6),
                          (TensorFunction, False, True, 3),
                          (TensorTimeFunction, False, False, 9),
                          (TensorTimeFunction, True, False, 6),
                          (TensorTimeFunction, False, True, 3)])
def test_tensor_eq(func1, symm, diag, expected):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid, symmetric=symm, diagonal=diag)
    for attr in f1[0]._fd:
        eq = Eq(f1, getattr(f1, attr))
        assert len(eq.evaluate._flatten) == expected

@pytest.mark.parametrize('func1', [VectorTimeFunction, TensorTimeFunction])
def test_save(func1):
    grid = Grid(tuple([5]*3))
    time = grid.time_dim
    f1 = func1(name="f1", grid=grid, save=10, time_order=1)
    assert all(ff.indices[0] == time for ff in f1)
    assert all(ff.indices[0] == time + time.spacing for ff in f1.forward)
    assert all(ff.indices[0] == time + 2*time.spacing for ff in f1.forward.forward)
    assert all(ff.indices[0] == time - time.spacing for ff in f1.backward)
    assert all(ff.shape[0] == 10 for ff in f1)

@pytest.mark.parametrize('func1', [TensorFunction, TensorTimeFunction])
def test_sympy_matrix(func1):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)

    sympy_f1 = f1.as_mutable()
    vec = sympy.Matrix(3, 1, np.random.rand(3))
    mat = sympy.Matrix(3, 3, np.random.rand(3, 3).ravel())
    assert all(sp - dp == 0 for sp, dp in zip(mat * f1, mat * sympy_f1))
    assert all(sp - dp == 0 for sp, dp in zip(f1 * vec, sympy_f1 * vec))

@pytest.mark.parametrize('func1', [VectorFunction, VectorTimeFunction])
def test_sympy_vector(func1):
    grid = Grid(tuple([5]*3))
    f1 = func1(name="f1", grid=grid)

    sympy_f1 = f1.as_mutable()
    mat = sympy.Matrix(3, 3, np.random.rand(3, 3).ravel())

    assert all(sp - dp == 0 for sp, dp in zip(mat * f1, mat * sympy_f1))

@pytest.mark.parametrize('func1', [TensorFunction, TensorTimeFunction])
def test_non_devito_tens(func1):
    grid = Grid(tuple([5]*3))
    comps = sympy.Matrix(3, 3, [1, 2, 3, 2, 3, 6, 3, 6, 9])

    f1 = func1(name="f1", grid=grid, components=comps)
    f2 = func1(name="f2", grid=grid)

    assert f1.T == f1
    assert isinstance(f1.T, sympy.ImmutableDenseMatrix)
    # No devito object in the matrix components, should return a pure sympy Matrix
    assert ~isinstance(f1.T, func1)
    # Can still multiply
    f3 = f2*f1.T
    assert isinstance(f3, func1)

    for i in range(3):
        for j in range(3):
            assert f3[i, j] == sum(f2[i, k] * f1[j, k] for k in range(3))

@pytest.mark.parametrize('func1', [TensorFunction, TensorTimeFunction])
def test_partial_devito_tens(func1):
    grid = Grid(tuple([5]*3))
    f2 = func1(name="f2", grid=grid)

    comps = sympy.Matrix(3, 3, [1, 2, f2[0, 0], 2, 3, 6, f2[0, 0], 6, 9])

    f1 = func1(name="f1", grid=grid, components=comps)

    assert f1.T == f1
    assert isinstance(f1.T, func1)
    # Should have original grid
    assert f1[0, 2].grid == grid
    # Can still multiply
    f3 = f2*f1.T
    assert isinstance(f3, func1)

    for i in range(3):
        for j in range(3):
            assert f3[i, j] == sum(f2[i, k] * f1[j, k] for k in range(3))

@pytest.mark.parametrize('shift, ndim', [(None, 2), (.5, 2), (.5, 3),
                                         (tuple([tuple([.5]*3)]*3), 3)])
def test_shifted_grad_of_vector(shift, ndim):
    grid = Grid(tuple([11]*ndim))
    f = VectorFunction(name="f", grid=grid, space_order=4)
    gf = grad(f, shift=shift).evaluate

    ref = []
    for i in range(len(grid.dimensions)):
        for j, d in enumerate(grid.dimensions):
            x0 = (None if shift is None else d + shift[i][j] * d.spacing if
                  type(shift) is tuple else d + shift * d.spacing)
            ge = getattr(f[i], 'd%s' % d.name)(x0=x0)
            ref.append(ge.evaluate)

    for i, d in enumerate(gf):
        assert d == ref[i]

@pytest.mark.parametrize('shift, ndim', [(None, 2), (.5, 2), (.5, 3), ((.5, .5, .5), 3)])
def test_shifted_div_of_vector(shift, ndim):
    grid = Grid(tuple([11]*ndim))
    v = VectorFunction(name="f", grid=grid, space_order=4)
    df = div(v, shift=shift).evaluate
    ref = 0

    for i, d in enumerate(grid.dimensions):
        x0 = (None if shift is None else d + shift[i] * d.spacing if
              type(shift) is tuple else d + shift * d.spacing)
        ref += getattr(v[i], 'd%s' % d.name)(x0=x0)

    assert df == ref.evaluate

@pytest.mark.parametrize('shift, ndim', [(None, 2), (.5, 2), (.5, 3),
                                         (tuple([tuple([.5]*3)]*3), 3)])
def test_shifted_div_of_tensor(shift, ndim):
    grid = Grid(tuple([11]*ndim))
    f = TensorFunction(name="f", grid=grid, space_order=4)
    df = div(f, shift=shift).evaluate

    ref = []
    for i, a in enumerate(grid.dimensions):
        elems = []
        for j, d in reversed(list(enumerate(grid.dimensions))):
            x0 = (None if shift is None else d + shift[i][j] * d.spacing if
                  type(shift) is tuple else d + shift * d.spacing)
            ge = getattr(f[i, j], 'd%s' % d.name)(x0=x0)
            elems.append(ge.evaluate)
        ref.append(sum(elems))

    for i, d in enumerate(df):
        assert d == ref[i]


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Oct  7 14:04:40 2018

@author: minjun
"""

import pomdp

if __name__ == "__main__":
    scan_para = [60, 360]
    pdp = pomdp.avPOMDP(scan_para)
    while (True):
        input_string = input(\
        "Input the angle and distance of a point or just type ENTER.\n")
        if (input_string == ""):
            input_data = None
        else:
            input_tmp = input_string.split()
            if (len(input_tmp) != 2):
                print("Invalid input.")
                continue;
            else:
                input_data = [int(input_tmp[0]), float(input_tmp[1])]
        alpha = pdp.sampleScanAngle()
        pdp.update(input_data, alpha)
        pdp.draw()
        print("present scan angle is:")
        print(alpha)


import logging
import argparse
import sys
import tehin

parser = argparse.ArgumentParser()
parser.add_argument('-l', '--log', help='Output verbosity', default='INFO')
parser.add_argument('-i', '--input_file', help='Input data file')
parser.add_argument('-o', '--output_file', help='Output data file')
parser.add_argument('-c', '--class_column', help='Column of the data containing the class')
parser.add_argument('-d', '--descriptive_columns', help='Names of columns containing descriptive data', nargs='+')
# parser.add_argument('-w', '--weighing', help='Weight calculation method', default='rf',
#                     choices=['tf', 'chi', 'ig', 'gr', 'delta', 'idf', 'rf'])
# parser.add_argument('-s', '--summing', help='Weight aggregation method', default='sum',
#                     choices=['sum', 'weighted_sum'])
# parser.add_argument('-b', '--basic_type', help='Basic type on which to split', default='person')

def main():
    # features = True
    # if features:
    args = parser.parse_args()
    logging.basicConfig(level=args.log, format='%(asctime)s %(message)s', stream=sys.stdout)
    logging.info('Loading data...')
    network = tehin.read_graph_from_features(args.input_file,
                                             feature_columns=args.descriptive_columns,
                                             class_column=args.class_column)
    # network = tehin.read_graph_from_net('pakdd.net')
    logging.info('Loaded!')
    network.full_feature_vectors('decomposition')
    network.export_json(args.output_file, args.descriptive_columns, args.class_column)
    # else:
    #     args = parser.parse_args()
    #     logging.basicConfig(level=args.log, format='%(asctime)s %(message)s', stream=sys.stdout)
    #     logging.info('Loading data...')
    #     network = tehin.read_graph_from_net('pakdd.net')
    #     logging.info('Loaded!')
    #
    #     network.set_basic_type(args.basic_type)
    #
    #     network.split_to_ratio(1.0, 0.0, 0.0)
    #     network.decompose(['person', 'C_level', 'person'], ['person_bought_C_level', 'C_level_bought_by_person'],
    #                     name='decomposition', weighing=args.weighing, summing=args.summing)
    #     network.full_feature_vectors('decomposition')
    #
    #     network.export_json('test_export.json')
#
#
if __name__ == '__main__':
    main()


import pygame
from pygame.sprite import Sprite
import game_functions as gf
class Alien(Sprite):
    def __init__(self, ai_settings, screen):
        super(Alien, self).__init__()
        self.screen = screen
        self.ai_settings = ai_settings
        self.image = pygame.image.load('images/player_o.bmp')
        self.rect = self.image.get_rect()
        self.rect.x = gf.random_place()[0]
        self.rect.y = gf.random_place()[1]
        self.x = float(self.rect.x)
    def blitme(self):
        self.screen.blit(self.image, self.rect)


from appium.webdriver import WebElement
from appium.webdriver.webdriver import WebDriver
import logging

from appium.webdriver.common.mobileby import MobileBy
from selenium.common.exceptions import NoSuchElementException

class BasePage:
    def __init__(self, driver: WebDriver = None):
        self.driver = driver

    def log_info(self, comment):
        logging.info(comment)

    def find(self, by, locator):
        self.log_info("find")
        self.log_info(by)
        self.log_info(locator)
        ele: WebElement = self.driver.find_element(by, locator)
        return ele

    def find_and_click(self, by, locator):
        self.log_info("find_and_click")
        self.log_info(by)
        self.log_info(locator)
        self.find(by, locator).click()

    def find_and_sentkeys(self, by, locator, text):
        self.log_info("find_and_sentkeys")
        self.log_info(by)
        self.log_info(locator)
        self.find(by, locator).send_keys(text)

    def get_toast_text(self):
        result = self.driver.find_element(MobileBy.XPATH, "//*[@class='android.widget.Toast']").get_attribute('text')
        return result

    def back(self, num=3):
        for i in range(num):
            self.driver.back()

    def swipe_find(self, text, max_swipe_count=5):
        count = 0
        while count <= max_swipe_count:
            try:
                # 如果找到了元素，就返回
                self.log_info("找元素")
                element = self.driver.find_element(MobileBy.XPATH, f"//*[@text='{text}']")
                return element

            # 如果没找到元素，就开始滑动找
            except NoSuchElementException:
                self.log_info("获取窗口大小")
                # 获取窗口的高宽，返回字典return {k: size[k] for k in ('width', 'height')}
                size = self.driver.get_window_size()
                # 取出高，宽
                width = size.get("width")
                height = size.get("height")

                # 滑动，找元素,X轴一般不变，取窗口的中间，从下往上滑动。下：整个窗口高度的4/5，上：整个窗口高度的1/5
                # duration:表示滑动的速度，一般设定2s，越慢越准确
                self.log_info(f"开始第{count}次滑动")
                self.driver.swipe(start_x=width / 2, start_y=height * 0.8, end_x=width / 2, end_y=height * 0.3,
                                  duration=2000)
                count += 1

            if count == max_swipe_count:
                raise NoSuchElementException(f"找了{max_swipe_count}次，没找到元素")


import os
import sys
sys.path.append("..")
from influence.influence_network import InfluenceNetwork
from influence.influence_uniform import InfluenceUniform
# from simulators.vec_env import VecEnv
from stable_baselines3.common.vec_env import SubprocVecEnv, VecNormalize, VecFrameStack
from recurrent_policies.PPO import Agent, FNNPolicy, GRUPolicy, IAMGRUPolicy, LSTMPolicy, IAMLSTMPolicy
import gym
import sacred
from sacred.observers import MongoObserver
import pymongo
# from sshtunnel import SSHTunnelForwarder
import numpy as np
import csv
import os
import time
from copy import deepcopy
from gym import spaces

def generate_path(path):
    """
    Generate a path to store e.g. logs, models and plots. Check if
    all needed subpaths exist, and if not, create them.
    """
    result_path = os.path.join("../results", path)
    model_path = os.path.join("../models", path)
    if not os.path.exists(result_path):
        os.makedirs(result_path)
    if not os.path.exists(model_path):
        os.makedirs(model_path)
    return path

def log(dset, infs, data_path):
    """
    Log influence dataset
    """
    generate_path(data_path)
    inputs_file = data_path + 'inputs.csv'
    targets_file = data_path + 'targets.csv'
    dset = np.reshape(np.swapaxes(dset, 0, 1), (-1, np.shape(dset)[2]))
    infs = np.reshape(np.swapaxes(infs, 0, 1), (-1, np.shape(infs)[2]))
    with open(inputs_file,'a') as file:
        writer = csv.writer(file)
        for element in dset:
            writer.writerow(element)
    with open(targets_file,'a') as file:
        writer = csv.writer(file)
        for element in infs:
            writer.writerow(element)

def add_mongodb_observer():
    """
    connects the experiment instance to the mongodb database
    """
    # MONGO_HOST = 'TUD-tm2'
    # MONGO_DB = 'scalable-simulations'
    # PKEY = '~/.ssh/id_rsa'
    # try:
    #     print("Trying to connect to mongoDB '{}'".format(MONGO_DB))
    #     server = SSHTunnelForwarder(
    #         MONGO_HOST,
    #         ssh_pkey=PKEY,
    #         remote_bind_address=('127.0.0.1', 27017)
    #         )
    #     server.start()
    #     DB_URI = 'mongodb://localhost:{}/scalable-simulations'.format(server.local_bind_port)
    #     # pymongo.MongoClient('127.0.0.1', server.local_bind_port)
    #     ex.observers.append(MongoObserver.create(DB_URI, db_name=MONGO_DB, ssl=False))
    #     print("Added MongoDB observer on {}.".format(MONGO_DB))
    # except pymongo.errors.ServerSelectionTimeoutError as e:
        # print(e)
    print("ONLY FILE STORAGE OBSERVER ADDED")
    from sacred.observers import FileStorageObserver
    ex.observers.append(FileStorageObserver.create('saved_runs'))

class Experiment(object):
    """
    Creates experiment object to interact with the environment and
    the agent and log results.
    """

    def __init__(self, parameters, _run, seed):
        """
        """
        self._run = _run
        self._seed = seed
        self.parameters = parameters['main']
        if self.parameters['policy'] == 'FNNPolicy':
            policy = FNNPolicy(self.parameters['obs_size'],
                self.parameters['num_actions'],
                self.parameters['hidden_size'],
                self.parameters['hidden_size_2'],
                self.parameters['num_workers']
                )

        elif self.parameters['policy'] == 'GRUPolicy':
            policy = GRUPolicy(self.parameters['obs_size'],
                self.parameters['num_actions'],
                self.parameters['hidden_size'],
                self.parameters['hidden_size_2'],
                self.parameters['num_workers']
                )

        self.agent = Agent(
            policy=policy,
            memory_size=self.parameters['memory_size'],
            batch_size=self.parameters['batch_size'],
            seq_len=self.parameters['seq_len'],
            num_epoch=self.parameters['num_epoch'],
            learning_rate=self.parameters['learning_rate'],
            total_steps=self.parameters['total_steps'],
            clip_range=self.parameters['epsilon'],
            entropy_coef=self.parameters['beta'],
            load=self.parameters['load_policy'],
            rollout_steps=self.parameters['rollout_steps']
            )
        global_env_name = self.parameters['env'] + ':global-' + self.parameters['name'] + '-v0'
        # global_env_name = 'tmaze:tmaze-v0'
        self.global_env = SubprocVecEnv(
            [self.make_env(global_env_name, i, seed) for i in range(self.parameters['num_workers'])],
            'spawn'
            )
        self.global_env = VecNormalize(self.global_env, norm_reward=True, norm_obs=True)

        if self.parameters['framestack']:
            self.global_env = VecFrameStack(self.global_env, n_stack=self.parameters['n_stack'])

        if self.parameters['simulator'] == 'local':
            self.data_path = parameters['influence']['data_path'] + str(_run._id) + '/'

            if self.parameters['influence_model'] == 'nn':
                self.influence = InfluenceNetwork(parameters['influence'], self.data_path, _run._id)
                if parameters['influence']['train']:
                    start = time.time()
                    self.collect_data(parameters['influence']['dataset_size'], self.data_path)
                    print('Data collection time: ', str(time.time() - start))
                    start = time.time()
                    loss = self.influence.learn()
                    print('Influence training time: ', str(time.time() - start))
                    self._run.log_scalar('influence loss', loss, 0)

            else:
                self.influence = InfluenceUniform(parameters['influence'])

            local_env_name = self.parameters['env']+ ':local-' + self.parameters['name'] + '-v0'
            self.env = SubprocVecEnv(
                [self.make_env(local_env_name, i, seed, self.influence) for i in range(self.parameters['num_workers'])],
                start_method='fork'
                )
            self.env = VecNormalize(self.env, norm_reward=True, norm_obs=True)

            if self.parameters['framestack']:
                self.env = VecFrameStack(self.env, n_stack=self.parameters['n_stack'])

        else:
            self.env = self.global_env

    def make_env(self, env_id, rank, seed=0, influence=None):
        """
        Utility function for multiprocessed env.
        :param env_id: (str) the environment ID
        :param num_env: (int) the number of environments you wish to have in subprocesses
        :param seed: (int) the inital seed for RNG
        :param rank: (int) index of the subprocess
        """
        def _init():
            if 'local' in env_id:
                env = gym.make(env_id, influence=influence, seed=seed+rank)
            else:
                env = gym.make(env_id, seed=seed+rank)
            # env = Monitor(env, './logs')
            # env.seed(seed + rank)
            return env
        # set_global_seeds(seed)
        return _init

    def run(self):

        obs = self.env.reset()
        step = 0
        episode_reward = 0.0
        episode_step = 0
        episode = 1
        start = time.time()
        done = [False]*self.parameters['num_workers']
        start = time.time()
        while step <= self.parameters['total_steps']:
            rollout_step = 0
            while rollout_step < self.parameters['rollout_steps']:
                if step % self.parameters['eval_freq'] == 0:
                    end = time.time()
                    print('Training time: ', end - start)
                    self.evaluate(step)
                    self.agent.save_policy()
                    start = time.time()
                if self.agent.policy.recurrent:
                    self.agent.reset_hidden_memory(done)
                    hidden_memory = self.agent.policy.hidden_memory
                else:
                    hidden_memory = None
                action, value, log_prob = self.agent.choose_action(obs)
                new_obs, reward, done, info = self.env.step(action)
                if self.parameters['render']:
                    self.env.render()
                    time.sleep(.5)
                self.agent.add_to_memory(obs, action, reward, done, value, log_prob, hidden_memory)
                obs = new_obs
                rollout_step += 1
                step += 1
                episode_step += 1
                episode_reward += np.mean(self.env.get_original_reward())
                if self.parameters['render']:
                    self.env.render()
                    time.sleep(.2)
                # episode_reward += np.mean(reward)
                if done[0]:
                    self.print_results(episode_reward, episode_step, step, episode)
                    episode_reward = 0.0
                    episode_step = 0
                    episode += 1

            self.agent.bootstrap(obs)

            if self.agent.buffer.is_full:
                start2 = time.time()
                self.agent.update()
                end2 = time.time()
                print('Update time:', end2 - start2)
        self.env.close()

    def collect_data(self, dataset_size, data_path):
        """Collect data from global simulator"""
        print('Collecting data from global simulator...')
        n_steps = 0
        # copy agent to not altere hidden memory
        agent = deepcopy(self.agent)
        while n_steps < dataset_size//self.parameters['num_workers']:
            reward_sum = 0.0
            done = [False]*self.parameters['num_workers']
            obs = self.global_env.reset()
            dset = []
            infs = []
            # NOTE: Episodes in all envs must terminate at the same time
            agent.reset_hidden_memory([True]*self.parameters['num_workers'])
            while not done[0]:
                n_steps += 1
                action, _, _= agent.choose_action(obs)
                # if self.parameters['render']:
                #     self.global_env.render()
                #     time.sleep(.5)
                obs, _, done, info = self.global_env.step(action)
                dset.append(np.array([i['dset'] for i in info]))
                infs.append(np.array([i['infs'] for i in info]))
                # breakpoint()
            log(dset, infs, data_path)
        print('Done!')

    def evaluate(self, step, collect_data=False):
        """Return mean sum of episodic rewards) for given model"""
        episode_rewards = []
        n_steps = 0
        # copy agent to not altere hidden memory
        agent = deepcopy(self.agent)
        print('Evaluating policy on global simulator...')
        while n_steps < self.parameters['eval_steps']//self.parameters['num_workers']:
            reward_sum = np.array([0.0]*self.parameters['num_workers'])
            done = [False]*self.parameters['num_workers']
            obs = self.global_env.reset()
            # NOTE: Episodes in all envs must terminate at the same time
            agent.reset_hidden_memory([True]*self.parameters['num_workers'])
            dset = []
            infs = []
            while not done[0]:
                n_steps += 1
                action, _, _ = agent.choose_action(obs)
                obs, reward, done, info = self.global_env.step(action)
                reward = self.global_env.get_original_reward()
                # if self.parameters['render']:
                #     self.global_env.render()
                #     time.sleep(.5)
                # reward_sum += np.array(reward)
                reward_sum = np.array([0.0]*self.parameters['num_workers'])
                if self.parameters['simulator'] == 'local':
                    dset.append(np.array([i['dset'] for i in info]))
                    infs.append(np.array([i['infs'] for i in info]))
                # breakpoint()
            if self.parameters['simulator'] == 'local':
                log(dset, infs, self.data_path)
            episode_rewards.append(reward_sum)
        if self.parameters['simulator'] == 'local':
            loss = self.influence.test(self.data_path + 'inputs.csv', self.data_path + 'targets.csv')
            self._run.log_scalar('influence loss', loss, step)
        self._run.log_scalar('mean episodic return', np.mean(episode_rewards), step)
        print('Done!')

    def print_results(self, episode_return, episode_step, global_step, episode):
        """
        Prints results to the screen.
        """
        print(("Train step {} of {}".format(global_step,
                                            self.parameters['total_steps'])))
        print(("-"*30))
        print(("Episode {} ended after {} steps.".format(episode,
                                                         episode_step)))
        print(("- Total reward: {}".format(episode_return)))
        print(("-"*30))

if __name__ == '__main__':
    ex = sacred.Experiment('scalable-simulations')
    ex.add_config('configs/default.yaml')
    add_mongodb_observer()

    @ex.automain
    def main(parameters, seed, _run):
        exp = Experiment(parameters, _run, seed)
        exp.run()


import numpy as np

serial_number = 9110
grid = np.zeros((300, 300), np.int32)

for index, data in np.ndenumerate(grid):
    x_addr = index[0] + 1
    y_addr = index[1] + 1
    rack_id = x_addr + 10
    power_level = rack_id * y_addr + serial_number
    power_level *= rack_id
    # get the 100's digit only
    power_level = int(power_level / 100) % 10
    power_level -= 5
    grid[index[0]][index[1]] = power_level

largest_power = -999999
largest_xy = None
for index, data in np.ndenumerate(grid):
    if index[0] < 298 and index[1] < 298:
        fuelcell = grid[index[0]:index[0] + 3, index[1]:index[1] + 3]
        power = np.sum(fuelcell)
        if power > largest_power:
            largest_power = power
            largest_xy = (index[0] + 1, index[1] + 1)

print(f'Part 1: {largest_xy}')

largest_power = -999999
largest_xys = None

for size in np.arange(1, 301):
    print(f'size: {size}')
    for index, data in np.ndenumerate(grid):
        if index[0] < (301 - size) and index[1] < (301 - size):
            fuelcell = grid[index[0]:index[0] + size, index[1]:index[1] + size]
            power = np.sum(fuelcell)
            if power > largest_power:
                largest_power = power
                largest_xys = (index[0] + 1, index[1] + 1, size)

print(f'Part 2: {largest_xys}')
print('done')


# imports
from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras import backend as K
import matplotlib.pyplot as plt
import numpy as np

# Parameters
batch_size = 128
num_classes = 10
epochs = 5
img_rows, img_cols = 28, 28

# Loading and splitting the mnist dataset
(x_train, lbl_train), (x_test, lbl_test) = mnist.load_data()

# Formatting
if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

# Setting up
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
y_train = keras.utils.np_utils.to_categorical(lbl_train, num_classes)
y_test = keras.utils.np_utils.to_categorical(lbl_test, num_classes)

# Defining model
model = Sequential()
model.add(Flatten())
model.add(Dense(64, activation = 'relu'))
model.add(Dense(64, activation = 'relu'))
model.add(Dense(num_classes, activation='softmax'))

# Compile model
model.compile(loss=keras.losses.categorical_crossentropy,
               optimizer=tf.keras.optimizers.SGD(lr = 0.1),
        metrics=['accuracy'],)

fit_info = model.fit(x_train, y_train,
           batch_size=batch_size,
           epochs=epochs,
           verbose=1,
           validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss: {}, Test accuracy {}'.format(score[0], score[1]))

# The salt and peppar function for our img.
def salt_and_pepper(input, noise_level):
    # salt and pepper noise
    a = np.random.binomial(size=input.shape, n=1, p=(1 - noise_level))
    b = np.random.binomial(size=input.shape, n=1, p=0.5)
    c = (a==0) * b
    return input * a + c

# For loop for different noise levels.
for i in [0, 0.2, 0.4, 0.6, 0.8, 1]:

    flattened_x_train = x_train.reshape(-1,784)
    flattened_x_train_seasoned = salt_and_pepper(flattened_x_train, noise_level=i)

    flattened_x_test = x_test.reshape(-1,784)
    flattened_x_test_seasoneed = salt_and_pepper(flattened_x_test, noise_level=i)

    latent_dim = 96

    input_image = keras.Input(shape=(784,))
    encoded = Dense(128, activation='relu')(input_image)
    encoded = Dense(latent_dim, activation='relu')(encoded)
    decoded = Dense(128, activation='relu')(encoded)
    decoded = Dense(784, activation='sigmoid')(decoded)

    autoencoder = keras.Model(input_image, decoded)
    encoder_only = keras.Model(input_image, encoded)

    encoded_input = keras.Input(shape=(latent_dim,))
    decoder_layer = Sequential(autoencoder.layers[-2:])
    decoder = keras.Model(encoded_input, decoder_layer(encoded_input))

    autoencoder.compile(optimizer='adam', loss='binary_crossentropy')

    fit_info_AE = autoencoder.fit(flattened_x_train_seasoned, flattened_x_train,
                    epochs=32,
                    batch_size=64,
                    shuffle=True,
                    validation_data=(flattened_x_test_seasoneed, flattened_x_test))

#following plotting code taken from https://blog.keras.io/building-autoencoders-in-keras.html
# Encode and decode some digits
# Note that we take them from the *test* set
encoded_imgs = encoder_only.predict(flattened_x_test_seasoneed)
decoded_imgs = decoder.predict(encoded_imgs)

n = 10  # How many digits we will display
plt.figure(figsize=(20, 4))
for i in range(n):
    # Display original
    ax = plt.subplot(2, n, i + 1)
    plt.imshow(flattened_x_test_seasoneed[i].reshape(28, 28))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # Display reconstruction
    ax = plt.subplot(2, n, i + 1 + n)
    plt.imshow(decoded_imgs[i].reshape(28, 28))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
print(i)
plt.show()


import random

import pygame
import os
from copy import copy, deepcopy
from tkinter import *
from tkinter.filedialog import asksaveasfile, askopenfilename

def scale_img(img, scale):
    return pygame.transform.scale(img, (img.get_width() / scale, img.get_height() / scale))

class Article:
    csv_titles = ''
    articles = []
    asset_path = ''
    scale = 4.0
    highest_priority = -1
    num_layers = 0
    num_articles_per_layer = []

    def __init__(self, layer, file_path, csv_data, priority=0):
        self.layer = layer
        self.file_path = file_path
        self.csv_data = csv_data
        self.priority = priority
        self.sprite = None
        Article.articles.append(self)

    def load_sprite(self):
        self.sprite = pygame.image.load(self.file_path)
        self.sprite = scale_img(self.sprite, Article.scale)
        print(f'LOADED: {self.file_path}')

    def get_sprite(self):
        if self.sprite is None:
            self.load_sprite()
        return self.sprite

    def draw(self, screen, pos=(0, 0)):
        if self.sprite is None:
            self.load_sprite()
        screen.blit(self.sprite, pos)

    def is_locked(self, outfit):
        return outfit.locked_layers[self.layer]

    @staticmethod
    def search(csv_data):
        for article in Article.articles:
            if article.csv_data == csv_data:
                return article
        return None

    @staticmethod
    def load_articles(asset_path, csv_file_path):
        Article.asset_path = asset_path
        with open(csv_file_path, 'r') as f:
            lines = f.readlines()

        Article.csv_titles = lines[0]
        for csv_line in lines[1:]:  # skip csv header
            Article.load_article(csv_line)
        Article.update()

    @staticmethod
    def load_article(csv_line):
        if csv_line.strip() == '':  # ignore blank lines
            return None

        properties = csv_line.split(',')
        layer = int(properties[0])
        article_file_path = os.path.join(Article.asset_path, properties[1])

        Article.highest_priority += 1
        article = Article(layer, article_file_path, csv_line, priority=Article.highest_priority)
        Article.sort()
        return article

    @staticmethod
    def sort():
        Article.articles.sort(key=lambda a: (a.layer, a.priority))

    @staticmethod
    def update():
        Article.num_layers = 1
        Article.num_articles_per_layer = []

        article_counter = 0
        Article.sort()
        last_layer = Article.articles[0].layer
        for article in Article.articles:
            if article.layer != last_layer:
                Article.num_articles_per_layer.append(article_counter)
                article_counter = 0
                Article.num_layers += 1
            article_counter += 1
            last_layer = article.layer
        Article.num_articles_per_layer.append(article_counter)

class Outfit:
    def __init__(self, articles=[]):
        self.articles = articles
        self.sorted = False
        self.locked_layers = [False] * Article.num_layers

    def toggle_article(self, article):
        if article is None:
            return
        if self.locked_layers[article.layer]:  # do nothing if layer is locked
            return

        self.sorted = False
        if article in self.articles:
            self.articles.remove(article)
            return
        self.articles.append(article)

    def toggle_lock(self, layer_idx):
        self.locked_layers[layer_idx] = not self.locked_layers[layer_idx]

    def remove_article(self, article):
        if article is None:
            return
        if self.locked_layers[article.layer]:  # do nothing if layer is locked
            return

        self.sorted = False
        if article in self.articles:
            self.articles.remove(article)

    def remove_all_articles(self):
        to_be_removed = []
        for article in self.articles:
            to_be_removed.append(article)
        for article in to_be_removed:
            self.remove_article(article)

    def remove_layer_articles(self, layer_id):
        to_be_removed = []
        for article in self.articles:
            if article.layer == layer_id:
                to_be_removed.append(article)
        for article in to_be_removed:
            self.remove_article(article)

    def sort(self):
        self.articles.sort(key=lambda a: (a.layer, a.priority))
        self.sorted = True

    def draw(self, screen, pos=(0, 0)):
        if not self.sorted:
            self.sort()

        for a in self.articles:
            a.draw(screen, pos)

    def save(self):
        locks = ','.join(str(e) for e in self.locked_layers)+'\n'
        lines = [locks]
        for a in self.articles:
            lines.append(a.csv_data)

        win = Tk()
        win.geometry("0x0")
        win.withdraw()
        f = asksaveasfile(initialfile='Untitled.outfit',
                          defaultextension=".outfit", filetypes=[("All Files", "*.*"), ("Outfit Files", "*.outfit")])
        if f is None:
            win.destroy()
            return
        f.writelines(lines)
        f.close()
        win.destroy()

    def load(self, file_path=None):
        use_tk = file_path is None
        if use_tk:
            win = Tk()
            win.geometry("0x0")
            win.withdraw()
            file_path = askopenfilename()
            if file_path is None:
                win.destroy()
                return

        print(f'Loading outfit: {file_path}')

        self.articles = []
        self.locked_layers = [False] * Article.num_layers
        with open(file_path, 'r') as f:
            lines = f.readlines()

        for csv_line in lines[1:]:  # first line has locked layer data
            if csv_line.strip() == '':  # ignore blank lines
                continue
            article = Article.search(csv_line)  # check if article is already in Article list
            if article is None:
                article = Article.load_article(csv_line)
            self.toggle_article(article)
        Article.update()
        self.locked_layers = list(e == 'True' for e in lines[0].split(','))
        if len(self.locked_layers) is not Article.num_layers:
            self.locked_layers = [False] * Article.num_layers

        if use_tk:
            win.destroy()

    def __deepcopy__(self, memo):
        new_articles = []
        for a in self.articles:
            new_articles.append(a)
        result = Outfit(new_articles)
        result.locked_layers = deepcopy(self.locked_layers)
        return result

    def randomize(self):
        self.remove_all_articles()
        for layer_idx in range(Article.num_layers):
            layer_articles = list(filter(lambda a: a.layer == layer_idx, Article.articles))
            temp = random.randrange(0, 100)
            while temp > 10:  # chance to not turn on any item in this layer
                # each time we randomly toggle an item in the layer,
                # make it less likely we toggle another in the same layer
                temp *= 0.15
                article_id = random.randrange(0, len(layer_articles))
                self.toggle_article(layer_articles[article_id])


from com import *
from time import *
from math import *
from random import random as rand
from numpy import sign

ANIM= True
DANCE= True
mood= 'meh'
frame=0# int #set manually if anim is off
t= 0 #float seconds

#w= 2560
#h= 1440
w,h= (int(2560//3),1440//2)#dev
#w,h= (2560,1440)
#w,h= (3840,2160)#4k
#w,h= (9075,6201)#poster

import numpy as np
import png
#import exr

import pygame
from pygame.locals import *

import ctypes as ct
from OpenGL.GL import *
from OpenGL.GL import shaders
from OpenGL.GL.EXT.texture_filter_anisotropic import *

def arr(*a):
	return np.array(a)

display= pygame.display
pygame.init()
display.gl_set_attribute(pygame.GL_ACCELERATED_VISUAL, 1)
display.gl_set_attribute(pygame.GL_CONTEXT_MAJOR_VERSION, 4)
display.gl_set_attribute(pygame.GL_CONTEXT_MINOR_VERSION, 5)
display.gl_set_attribute(pygame.GL_CONTEXT_PROFILE_MASK, pygame.GL_CONTEXT_PROFILE_CORE)
#display.gl_set_attribute(pygame.GL_CONTEXT_DEBUG_FLAG, 1)
display.gl_set_attribute(pygame.GL_FRAMEBUFFER_SRGB_CAPABLE, 1)

resolution= (w,h)
pygame.display.set_mode(resolution, DOUBLEBUF | OPENGL)
pygame.display.set_caption('____________________________')

'''
from ctypes import *
def py_cmp_func(a, b):
	print((a,b))
	return
cmp_func = CFUNCTYPE(
	None, # void ; ctypes using None to represent void is shockingly undocumented
	c_size_t,# GLenum source
	c_size_t,# GLenum type
	c_int,# GLuint id
	c_size_t,# GLenum severity
	c_int,# GLsizei length
	POINTER(c_char),# const GLchar* message
	POINTER(c_size_t)# const void* userParam)
	)(py_cmp_func)
glDebugMessageCallback(cmp_func,c_voidp(0))
glEnable(GL_DEBUG_OUTPUT)
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS)
'''

tex_alb= None
tex_flw= None
tex_emi= None
def loadtexes():
	def loadtex(f,i=0):
		try:
			img= png.Reader(f).read() #(width, height, values, info)
			img_w= img[0]
			img_h= img[1]
			img_rast= np.flip(np.array(list(img[2]),dtype='uint8'),0).flatten()
			assert(len(img_rast)==img_w*img_h*4)
		except Exception as e:
			print(e)
			img_rast= np.zeros(w*h*4)

		tex= glGenTextures(1)
		glActiveTexture(GL_TEXTURE0+i)
		glBindTexture(GL_TEXTURE_2D, tex);
		MIPS= 4
		glTexStorage2D(GL_TEXTURE_2D, MIPS, GL_RGBA8, img_w,img_h)#memory uninitialized, inits mipmap level range
		glTexSubImage2D(GL_TEXTURE_2D, 0,0,0, img_w,img_h, GL_RGBA, GL_UNSIGNED_BYTE, img_rast)
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, MIPS)
		glGenerateMipmap(GL_TEXTURE_2D)
		return tex

	global tex_alb
	global tex_flw
	global tex_emi
	def chd(t):
		if t!=None:	glDeleteTextures(t)
	chd(tex_alb)
	chd(tex_flw)
	chd(tex_emi)
	tex_alb= loadtex('tex_albedo.png',   0)
	tex_flw= loadtex('tex_flow.png',     1)
	tex_emi= loadtex('tex_emission.png', 2)

prog_outer= None
prog_inner= None
def loadprogs():
	def a(frag):
		with open("com.glsl") as f:
			com= f.read()
		with open("panopticube.vsh") as f:
			vsh_src= f.read()
		with open(frag) as f:
			fsh_src= f.read()
		try:
			pp= lambda f,D: ''.join([
				'#version 430\n',
				com,
				*['#define %s 1\n'%d for d in D],
				'#line 1\n',
				f
			])
			vsh_src= pp(vsh_src,[])
			fsh_src= pp(fsh_src,[])
			v_p= shaders.compileShader(vsh_src, GL_VERTEX_SHADER)
			f_p= shaders.compileShader(fsh_src, GL_FRAGMENT_SHADER)
			p= shaders.compileProgram(v_p,f_p)
			return p

		except Exception as e:
			print('\nSHADERROR\n')
			e= str(e)[:500]
			e= e.replace('\\\\n','\n')
			e= e.replace(  '\\n','\n')
			e= e.replace(  '\\t','\t')
			e= e.replace(  '\\t','\t')
			e= e.replace(  '\\','')
			e= e.replace('\\\\','')#fuck
			print(e)
			exit()
			return 'failure'
	global prog_inner
	global prog_outer
	prog_inner= a("panopticube_inner.fsh")
	prog_outer= a("panopticube_outer.fsh")

import obj
mesh= obj.load('cube_uvn.obj')
#mesh= obj.load('caveblocks.obj')

appstart= perf_counter()
profile_start= perf_counter()

glViewport(0,0,w,h)

import viewmat
view= viewmat.state()
#view.r[1]= -.2#initial rotation
view.r[0]= 3/8
view.r[1]= 1/4.5

def render():
	glClearColor(0.01,0.01,0.01,0)
	glClear(GL_COLOR_BUFFER_BIT+GL_DEPTH_BUFFER_BIT)

	glUseProgram(prog_inner)

	if ANIM and DANCE:
		if mood=='meh':
			yaw= sin(t*.2)
			yaw*= abs(yaw)
			view.r[0]+= yaw*.002

			roll= sin(t*.1 )
			roll= pow(abs(roll),420)*sign(roll)
			view.r[1]+= roll*.06

			view.s= .75

		if mood=='happy':
			view.r[0]+= sin(t* 6 )*.008  \
					   +sin(t* .6)*.005
			view.r[1]+= cos(t*14 )*.015

			view.s= .8

		if mood=='angery':
			view.s= .7+sin(t*TAU*14.321+3)/24
			view.r[0]+= 0 if rand()<.98 else 1/4

	vm= view.do(w,h)
	mmv= vm.v
	mp=  vm.p
	glUniformMatrix4fv(0,1,True,mmv)
	glUniformMatrix4fv(1,1,True,mp)
	glUniform1f(2, t) #t
	glUniform3f(3, 0.05,0.05,0.05)#ambient
	glUniform3f(4, 0.1 ,0.6 ,1.  )#reflective
	glUniform3f(5, 0.7 , .85,0.95)#albedo
	glUniform1f(6, .5 ) #rough
	glUniform1f(8, .4) #fresnel magnitude

	glEnable(GL_BLEND)
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)#transparent

	glEnable(GL_DEPTH_TEST)
	glDepthFunc(GL_LESS)

	glEnable(GL_CULL_FACE)
	glFrontFace(GL_CW)

	mesh()

	glUseProgram(prog_outer)
	if mood=='meh':
		view.s= 1.0
	if mood=='happy':
		view.s= 1.0
	if mood=='angery':
		view.s= 1.5+sin(t*TAU*16.543)/16
	vm= view.do(w,h)#outer cube
	mmv= vm.v
	mp=  vm.p
	glUniformMatrix4fv(0,1,True,mmv)
	glUniformMatrix4fv(1,1,True,mp)
	glUniform1f(2, t)#ime
	glUniform1f(6, .2 )#rough
	glUniform1f(8, .25) #fresnel magnitude

	glUniform1i( 9, 0)#tex
	glUniform1i(10, 1)
	glUniform1i(11, 2)
	mesh()

	pygame.display.flip()

loadprogs()
mdown= False
def loop():
	global t
	global frame
	while 1:
		#view.update()
		render()
		if ANIM:
			t= perf_counter()-appstart
			frame+=1
		sleep(1./60.)
		if frame%30==0: #recompile all the t lmao
			#todo file modify hook
			try:
				loadprogs()
				loadtexes()
			except Exception as e:
				print('bad '+str(e))

		#input
		for e in pygame.event.get():
			if (e.type == QUIT) or (e.type == KEYUP and e.key == K_ESCAPE):
				return
			if e.type==MOUSEMOTION:
				if(pygame.mouse.get_pressed()[0]):
					w,h = pygame.display.get_surface().get_size()
					cx,cy= pygame.mouse.get_pos()
					cx=   cx - w//2
					cy= h-cy - h//2
					cx/= w
					cy/= h
					view.r= [cx,cy]

			if e.type==TEXTINPUT:
				continue

			if e.type==MOUSEBUTTONDOWN:
				if e.button==1:#LMB
					continue
				if e.button==4:#wheel
					view.z-=1
				if e.button==5:#wheel
					view.z+=1
loop()

rast= glReadPixels(0,0,w,h, GL_RGB,GL_FLOAT)
pygame.display.flip()

print('render t %sms'%((perf_counter()-profile_start)*1000))

profile_start= perf_counter()

print(rast.shape)
rast= rast*(-1+2**8)
rast= rast.astype(np.uint8).flatten()
img= png.Writer(
	size=(w,h),
	bitdepth=8,
	greyscale=False,
	alpha= False,
	compression=4
	)
img.write_array( open('./out.png','wb'), rast )

print('save t %sms'%((perf_counter()-profile_start)*1000))


import threading
import traceback

ALLOWED_LOCKS_CHAINS = [
    ('clusters', 'nodes'),
    ('tasks', 'clusters'),
    ('tasks', 'clusters', 'nodes'),
    ('tasks', 'nodes'),
]

class Lock(object):
    """Locking table info. Includes traceback info of locking call
    """

    def __init__(self, table):
        self.trace_lst = traceback.extract_stack()
        self.table = table

context = threading.local()

class LockTransitionNotAllowedError(Exception):
    def __init__(self):
        msg = "Possible deadlock found while attempting " \
              "to lock table: '{0}'. Lock transition is not allowed: {1}. " \
              "Traceback info: {2}".format(
                  context.locks[-1].table,
                  ', '.join([lock.table for lock in context.locks]),
                  self._get_locks_trace()
              )
        Exception.__init__(self, msg)

    def _get_locks_trace(self):
        msg = ""
        for lock in context.locks:
            msg += "\t{0}\n".format('-' * 70)
            msg += "\ttable: {0}\n".format(lock.table)
            msg += "\ttrace: \n"
            for entry in traceback.format_list(lock.trace_lst):
                msg += "\t\t{0}".format(entry)
        return msg

def clean_locks():
    """Context must be cleaned when transaction ends
    """
    context.locks = []

def handle_lock(table):
    """Storing table lock information into locks context.
    :param table: locking table name string value
    """
    lock = Lock(table)

    if not hasattr(context, 'locks'):
        context.locks = []

    # If locking the same table lock is already registered
    if len(context.locks) > 0 and context.locks[-1].table == lock.table:
        return

    # Registering locked table
    context.locks.append(lock)

    # Nothing to check if only one table locked
    if len(context.locks) == 1:
        return

    # Checking lock transition is allowed
    transition = (context.locks[-2].table, context.locks[-1].table)
    if transition not in ALLOWED_LOCKS_CHAINS:
        raise LockTransitionNotAllowedError()


from collections import deque
import sys

input = sys.stdin.readline

def isPossible(channel):
    global broken
    for num in str(channel):
        if broken[int(num)]:
            return False
    return True

N = int(input())
M = int(input())

if M == 0:
    answer = min(len(str(N)), abs(100-N))
else:
    queue = deque([N])
    broken = [False for i in range(10)]
    for i in input().split():
        broken[int(i)] = True

    answer = abs(100-N)
    for i in range(0, 1000000):
        if isPossible(i):
            answer = min(answer, len(str(i)) + abs(N-i))

print(answer)


#! /usr/bin/python3
import sys

def parse_input(path):
    pairs = {}
    rules = {}
    for line in open(path):
        if not pairs:
            polymer = line.strip()
            for a, b in zip(polymer, polymer[1:]):
                pairs[a + b] = pairs.get(a + b, 0) + 1
        elif line.strip():
            k, v = line.split('->')
            outers = k.strip()
            inner = v.strip()
            rules[outers] = [outers[0] + inner, inner + outers[1]]
    return pairs, rules

def iterate(pairs, rules):
    new_pairs = {}
    for pair, count in pairs.items():
        a, b = rules[pair]
        new_pairs[a] = new_pairs.get(a, 0) + count
        new_pairs[b] = new_pairs.get(b, 0) + count
    return new_pairs

def get_freqs(pairs):
    freqs = {}
    for pair, count in pairs.items():
        freqs[pair[0]] = freqs.get(pair[0], 0) + count
        freqs[pair[1]] = freqs.get(pair[1], 0) + count
    for k, v in freqs.items():
        if v & 1: # The first and last element in the polymer will match this case
            v += 1
        freqs[k] = v // 2 # Account for every element (except first/last) being in 2 pairs
    return sorted(freqs.values())

def main(input_file):
    pairs, rules = parse_input(input_file)
    for i in range(40):
        if i == 10:
            freqs = get_freqs(pairs)
            print("Part 1:", freqs[-1] - freqs[0])
        pairs = iterate(pairs, rules)
    freqs = get_freqs(pairs)
    print("Part 2:", freqs[-1] - freqs[0])

if __name__ == '__main__':
    main(sys.argv[1])


'''
Escaneando a rede utilizando ping.

Requirements:
- ping3
- tqdm
pip3 install ping3 tqdm
'''

from ping3 import ping
from tqdm import tqdm

timeout= 0.05

o1_ini, o1_end = 192, 192
o2_ini, o2_end = 168, 168
o3_ini, o3_end = 0, 0
o4_ini, o4_end = 1, 254

def get_n_ips():
    n_o1 = o1_end-o1_ini+1
    n_o2 = o2_end-o2_ini+1
    n_o3 = o3_end-o3_ini+1
    n_o4 = o4_end-o4_ini+1
    n = n_o1 * n_o2 * n_o3 * n_o4
    return(n)

def ip_generator():
    for o1 in range(o1_ini, o1_end+1):
        for o2 in range(o2_ini, o2_end+1):
            for o3 in range(o3_ini, o3_end+1):
                for o4 in range(o4_ini, o4_end+1):
                    ip = f'{o1}.{o2}.{o3}.{o4}'
                    yield ip

hosts = {}

print('Escaneando rede...')
for ip in tqdm(ip_generator(), total = get_n_ips()):
    time = ping(ip, timeout=timeout)
    if time:
        hosts[ip] = time

print('Hosts online:')
for host in hosts:
    print(host)
print('Tempo médio:',sum(hosts.values())/len(hosts.values()), 'segundos')


import numpy as np
import math
from matplotlib import pyplot as plt
from matplotlib import animation

# Line parameter definition
C = 100E-6
L = 250E-9
R = 0.05
G = 0.025
Zo = math.sqrt(L / C)
vo = 1.0 / math.sqrt(L * C)
d = 0.5
ncells = 100

cfln = 0.99
simtime = .1

# compute the discretization
dx = d / ncells
dt = cfln * dx / vo
nx = ncells + 1
nt = math.floor((simtime / dt)/1000)
print(nt)
print('Running to time step sample {} at spacial sample distance of {}'.format(nt, nx))

# Internal Resistance
Rg = 50
RL = 0

# Voltage Source spec
Vamp = 1.

# initialize line voltages and currents to zero:
V = np.zeros(nx + 1, order='F')
I = np.zeros(nx - 1, order='F')

# TODO: Create Class for all respective update equations

# Set time step to 1 for initial program

def voltage_update(n):
    """
     Update interior node voltages
     compute the multiplier coefficient:
    """
    global t
    t = dt*(n-0.5)

    cv = dt / (C * dx)

    # recursively update the line voltage at all interior nodes
    for k in range(0, nx - 1):
        V[k] = V[k] - cv * (I[k] - I[k - 1])

def voltage_source_update(n):
    """
    In-line function to update the source voltage V(1)
    """
    Vs = voltage_source(n)

    if Rg > 0:
        # compute the multiplier coefficients (from (2.62))
        b1 = (C * dx * 0.5) / dt
        b2 = 0.5 / Rg
        c1 = 1.0 / (b1 + b2)
        c2 = b1 - b2
        V[0] = c1 * (c2 * V[0] - I[0] + (Vs / Rg))

    else:
        V[0] = Vs

def voltage_load_update(RL):
    if RL == 0:
        V[nx] = 0
    else:
        b1 = (C * dx * 0.5) / dt
        b2 = 0.5 / RL
        c1 = 1.0 / (b1 + b2)
        c2 = b1 - b2

        V[nx-1] = c1 * (c2 * V[nx-1] + I[nx-2])

def current_update():
    """
    In-line function to compute the update of the line current
    interior to the homogeneous line
    """
    # Compute the multiplier coefficient:
    ci = dt / (L * dx)
    for k in range(0, nx-1):
        I[k] = I[k] - (ci * (V[k + 1] - V[k]))

def voltage_source(n, source_type='unit_step'):
    Vs = 0
    if source_type == 'unit_step':
        if n >= 0:
            Vs = Vamp
    else:
        Vs = 0

    return Vs

fig = plt.figure()
ax = plt.axes(xlim=(0,d), ylim=(-2,2))
line, = ax.plot([], [], lw=2)

def animate(n):
    x = np.linspace(0, d, nx+1)
    voltage_update(n)
    voltage_source_update(n)
    voltage_load_update(RL)

    current_update()
    print(I)
    print(V)
    print(len(x), len(V))
    line.set_data(x, V)
    return line,

def init():
    line.set_data([], [])
    return line,

anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames = 200, interval=20, blit=True)

plt.show()


# pylint: disable=too-many-ancestors
import importlib
import torch
import pytorch_lightning as pl
from utils import model_dictionary, loss_dictionary
from torch.optim.lr_scheduler import ReduceLROnPlateau

class DTSModel(pl.LightningModule):
    def __init__(self, config, device):
        super().__init__()

        self.to_device = device
        self.model_name = config['model_name']
        self.model_params = config['model_params']

        self.loss_fn_type = config['loss_fn_type']
        self.loss_fn_params = config['loss_params']

        self.model = self.get_model()
        self.loss_fn = self.get_loss_fn()
        self.float()

    def get_model(self):
        module = importlib.import_module(model_dictionary[self.model_name][0])
        model_class = getattr(module, model_dictionary[self.model_name][1])
        return model_class(self.to_device, **self.model_params)

    def get_loss_fn(self):
        module = importlib.import_module(loss_dictionary[self.loss_fn_type][0])
        loss_fn_class = getattr(module, loss_dictionary[self.loss_fn_type][1])
        return loss_fn_class(**self.loss_fn_params)

    def forward(self, inputs):
        return self.model(inputs)

    def training_step(self, batch, batch_idx):
        inputs, labels = batch
        outputs = self(inputs)
        loss = self.loss_fn(outputs, labels)
        self.log('train_loss', loss)
        return loss

    def validation_step(self, batch, batch_idx):
        inputs, labels = batch
        outputs = self(inputs)
        loss = self.loss_fn(outputs, labels)
        self.log('val_loss', loss)

    def test_step(self, batch, batch_idx):
        inputs, labels = batch
        outputs = self(inputs)
        loss = self.loss_fn(outputs, labels)
        self.log('test_loss', loss)

    def configure_optimizers(self):
        optimizer = torch.optim.AdamW(self.parameters(),lr=self.model_params['lr'])
        scheduler = ReduceLROnPlateau(
            optimizer,
            mode='min',
            factor=0.5,
            patience=10,
            verbose=True)
        return {'optimizer': optimizer, 'lr_scheduler': scheduler, 'monitor': 'val_loss'}


import datetime
import urllib

from django.core.context_processors import csrf
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext

from animals.models import *
from content.models import Comment
from system.models import Region
from system.views import get_monthes

def list(request):
    page = request.GET.get('page', 1)
    items_filter = {
        'visibility': True,
        'deleted': False,
    }

    # filters
    filter = {}
    for field in ('age__lte', 'age__lte'):
        if request.GET.has_key(field) and request.GET[field]:
            filter[field] = request.GET[field]

    items_filter.update(filter)

    # try to find region
    try:
        region = Regions.objects.get(pk=int(request.GET.get('region_id', 0)))
        items_filter['region'] = region
        filter['region'] = region.city_name_ru
    except: pass

    # try to find breed
    try:
        breed = Breed.objects.get(pk=int(request.GET.get('breed_id', 0)))
        items_filter['breed'] = breed
        filter['breed'] = breed.name
    except: pass

    # get filtered items
    objects = Animal.objects.select_related().filter(**items_filter)

    # filter by search text
    if request.GET.has_key('q') and request.GET['q']:
        filter['q'] = request.GET['q']
        objects = objects.filter(Q(title__icontains=request.GET['q']), Q(description__icontains=request.GET['q']))

    paginator = Paginator(objects, 10)
    try:
        items = paginator.page(page)
    except PageNotAnInteger:
        items = paginator.page(1)
    except EmptyPage:
        items = paginator.page(paginator.num_pages)

    data = {
        'items': items,
        'filter': filter,
        'user_menu': 'animals',
        'start_index': items.start_index(),
        'end_index': items.end_index(),
        'url': urllib.urlencode(filter),
    }
    return render_to_response('animals/animals-list.html', data, context_instance=RequestContext(request))

def show(request, id):
    item = Animal.objects.select_related().get(pk=id, visibility=True, deleted=False)

    filter = {}
    for field in ('age__lte', 'age__lte', 'q', 'region_id', 'breed_id'):
        if request.GET.has_key(field) and request.GET[field]:
            filter[field] = request.GET[field]

    if request.member and request.GET.has_key('add-comment'):
        new_comment = Comment(**{
            'entity': 'animals',
            'id_entities': item.id,
            'user': request.member,
            'comment': request.POST['comment'],
            'visibility': True,
        })
        new_comment.save()
        return redirect('?')

    data = {
        'item': item,
        'filter': filter,
        'url': urllib.urlencode(filter),
        'other': Animal.objects.select_related().filter(visibility=True, deleted=False).exclude(pk=item.id)[0:3],
        'comments': Comment.objects.select_related().filter(entity='animals', id_entities=item.id, visibility=True).order_by('-created')[0:3]
    }
    return render_to_response('animals/animals-item.html', data, context_instance=RequestContext(request))

def ajax_get_breeds(request):
    objects = Breed.objects.filter(name__icontains=request.GET.get('q', ''))
    output = "\n".join(['%s|%s' % (o.id, o.name) for o in objects])
    return HttpResponse(output)

def my(request):
    page = request.GET.get('page', 1)
    objects = Animal.objects.select_related().filter(user=request.member, deleted=False)
    paginator = Paginator(objects, 10)
    try:
        items = paginator.page(page)
    except PageNotAnInteger:
        items = paginator.page(1)
    except EmptyPage:
        items = paginator.page(paginator.num_pages)

    data = {
        'items': items,
        'user_menu': 'list',
        'start_index': items.start_index(),
        'end_index': items.end_index(),
    }
    return render_to_response('animals/animals-my.html', data, context_instance=RequestContext(request))

def edit(request, id=None):
    item = {} if not id else Animal.objects.select_related().get(pk=id, deleted=False)

    data = {
        'item': item,
        'user_menu': 'edit',
        'types': AnimalType.objects.all(),
        'genders': ANIMAL_GENDERS,
        'days': range(1, 31),
        'monthes': get_monthes(True),
        'years': range(datetime.datetime.now().year, 1970, -1)
    }
    data.update(csrf(request))

    if request.method == 'POST':
        if id:
            form = AnimalForm(request.POST, instance=item)
        else:
            form = AnimalForm(request.POST)
            data['item'] = request.POST

        if form.is_valid():
            item = form.save(commit=False)
            item.user = request.member
            item.region = request.member.region
            item.visibility = True
            item.birth_day = '%s-%s-%s' % (request.POST.get('year'), request.POST.get('month'), request.POST.get('day'))
            item.save()

            for i in range(1, 4):
                if request.FILES.has_key('image%s' % i):
                    img = AnimalImage(animal=item, image=request.FILES['image%s' % i])
                    img.save()

            return redirect('/my/animals/?result=success')
        else:
            data['errors'] = form.errors
            data['result'] = 'failed'

    return render_to_response('animals/animals-edit.html', data, context_instance=RequestContext(request))

def delete(request, id=None):
    if id:
        Animal.objects.get(pk=id, user=request.member).delete()

    return redirect('/my/animals/?result=success')


# Standard Library
from datetime import datetime, timedelta
# Project Files
from iot_time_series import IoTTimeSeries

class DataFetcher(object):
    """ Fetch data from the MindSphere IoT Time Series Service. """
    def __init__(self, auth_token, asset_id, aspect):
        self.auth_token = auth_token
        self.asset_id = asset_id
        self.aspect = aspect
        # Set the time range to 5 days. Note that 2000 is the maximum number of
        # time series data points to be retrieved.
        self.fmt = '%Y-%m-%dT%H:%M:%S.%f'
        self.now = datetime.utcnow()
        # Required time format: 'YYYY-mm-ddTHH:MM:SS.sssZ'.
        self.start = (self.now - timedelta(days=5)).strftime(self.fmt)[:-3] + 'Z'
        self.end = self.now.strftime(self.fmt)[:-3] + 'Z'

    def fetch_data(self, variable):
        """ Read the timeseries data of the variable. """
        timestamps = []
        values = []
        response = IoTTimeSeries().read(
            self.auth_token,
            self.asset_id,
            self.aspect,
            _from=self.start,
            to=self.end,
            select=variable
        )
        if response.status_code == 200:
            data = response.json()
            # Read the latest record if the last 5 days has no data points.
            if not data:
                response = IoTTimeSeries().read(
                    self.auth_token,
                    self.asset_id,
                    self.aspect,
                    select=variable
                )
                if response.status_code == 200:
                    data = response.json()
            # Read timestamps and values.
            for data_point in data:
                timestamps.append(data_point['_time'])
                values.append(data_point[variable])
        return (timestamps, values)


import pandas as pd

from lib.scrape import post_soup_from_url
from db.mongo import MyMongo

def create_url(name_and_url):
    url_base = 'http://info.childcare.go.kr/info/cfvp'
    return url_base + name_and_url.split('.', 1)[1]

url = 'http://info.childcare.go.kr/info/cfvp/VioltactorSlL.jsp'
data = {
    'total': '69',
    'offset': '1',
    'limit': '70',
}
soup = post_soup_from_url(url, data)
table = soup.find('table', class_='table_childcare')
data = [[''.join(td.stripped_strings)+td.a['href'] if td.find('a') else
         ''.join(td.stripped_strings)
         for td in row.find_all('td')]
        for row in table.find_all('tr')]
header = [[''.join(th.stripped_strings)
           for th in thead.find_all('th')]
          for thead in table.find_all('thead')]
df = pd.DataFrame(data[1:], columns=header[0])
df['detail_url'] = df.apply(lambda row: create_url(row['이름']), axis=1)
df['이름'] = df.apply(lambda row: row['이름'].split('.')[0], axis=1)

with MyMongo() as db:
    db.delete_and_insert_df('kindergarten', 'violator', df)


from sentry_config.exceptions import CriteriaNotMetError, CriteriaDescriptionError

class SentryCriteria:
    """ This class represents the criteria a value must follow in order to be considered valid. Also has code to allow
    for the conversion of passed values. A derived class of SentryCriteria can either only do criteria checks, only
    do conversions of the value, or can do both. """
    def criteria(self, value):
        """
        This method, if overridden, should contain if statements against the value to validate.
        If any of the if statements fail, a string describing the condition which failed should be returned.
        Args:
            value: The value to validate.
        Returns: A string in the case of failing to validate describing why it wasn't valid.
        """
        pass

    @property
    def required_type(self):
        """ If overridden, the type returned here should be the type that is to be used to convert the option value. """
        return type

    @property
    def type_error_message(self):
        """ If overridden, the return value should be a string describing what type is required. Note that if
        required_type is overridden and the value fails to convert and this method is not overridden, then an
        exception of type CriteriaNotMetError will be raised. """
        return ""

    def convert(self, option_name, value):
        try:
            if self.required_type is bool:  # Another hack to make sure booleans work.
                value = value == "True" or value == "1"  # If value is "" it is set to False...
            value = self.required_type(value)
            return value
        except ValueError:
            if self.type_error_message == "":
                raise CriteriaDescriptionError(option_name)
            raise CriteriaNotMetError(option_name, self.type_error_message)

    def __call__(self, option_name, value):
        """
        When called, this will either convert the option value to the specified type (if required_type is not type),
        run the value through criteria checks and raise a CriteriaNotMetError in the event of an error string being
        returned, or will do both of these things, with the conversion preceding the criteria checks.
        Args:
            option_name: The name of the option being validated. For use in the exception.
            value: The option value being converted/validated.
        Returns: None, or the converted value.
        """
        value_converted = False
        if self.required_type is not type:
            value = self.convert(option_name, value)
            value_converted = True

        failed_criteria_message = self.criteria(value)
        if failed_criteria_message is not None:
            raise CriteriaNotMetError(option_name, failed_criteria_message)

        if value_converted:
            return value


from collections import deque
import sys

n = int(input())
deq = deque()

for i in range(n):
  op = sys.stdin.readline().rstrip().split()

  if 'push_front' in op[0]:
    deq.appendleft(op[1])
  elif 'push_back' in op[0]:
    deq.append(op[1])
  elif 'pop_front' in op[0]:
    print(deq.popleft()) if deq else print(-1)
  elif 'pop_back' in op[0]:
    print(deq.pop()) if deq else print(-1)
  elif 'size' in op[0]:
    print(len(deq))
  elif 'empty' in op[0]:
    print(0) if deq else print(1)
  elif 'front' in op[0] :
    print(deq[0]) if deq else print(-1)
  elif 'back' in op[0]:
    print(deq[-1]) if deq else print(-1)


#!/usr/bin/env python
#
# Lara Maia <dev@lara.monster> 2015 ~ 2023
#
# The Steam Tools NG is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# The Steam Tools NG is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/.
#

import logging
from typing import AsyncGenerator, Callable, Awaitable

import aiohttp

from stlib import login, universe, community
from . import utils
from .. import i18n, config

_ = i18n.get_translation
log = logging.getLogger(__name__)

async def main(
        steamid: universe.SteamId,
        wait_available: Callable[[], Awaitable[None]],
) -> AsyncGenerator[utils.ModuleData, None]:
    await wait_available()

    identity_secret = config.parser.get("login", "identity_secret")
    session = community.Community.get_session(0)

    if not identity_secret:
        config.new("confirmations", "enable", "false")
        module_data = utils.ModuleData(error=_("The current identity secret is invalid."), info=_("Waiting Changes"))

        async for data in utils.timed_module_data(10, module_data):
            yield data

        return

    deviceid = config.parser.get("login", "deviceid")

    if not deviceid:
        log.warning(_("Unable to find deviceid. Generating from identity."))
        deviceid = universe.generate_device_id(identity_secret)
        config.new("login", "deviceid", deviceid)

    try:
        confirmations = await session.get_confirmations(identity_secret, steamid, deviceid)
    except AttributeError as exception:
        log.error(str(exception))
        module_data = utils.ModuleData(error=_("Error when fetch confirmations"), info=_("Waiting Changes"))
    except ProcessLookupError:
        module_data = utils.ModuleData(error=_("Steam is not running"), info=_("Waiting Changes"))
    except login.LoginError:
        module_data = utils.ModuleData(error=_("Not logged in"), action="login")
    except aiohttp.ClientError:
        module_data = utils.ModuleData(error=_("Check your connection. (server down?)"), info=_("Waiting Changes"))
    else:
        module_data = utils.ModuleData(action="update", raw_data=confirmations)

    async for data in utils.timed_module_data(30, module_data):
        yield data


"""

OUTPUT FORMAT:
<time>,<mw_device-id>,<mw_region>,<doppler-frequency-value>,<pressure_sensor_device-id>,<pressure_sensor_region>,<pressure-value>,<ir_fence_device-id>,<ir_fence_region>,<ir-fence-value>

"""

import socket
import sys
import time
import random
from datetime import datetime

MEAN_FREQENCY = 120
VARIANCE = 40
MEAN_WEIGHT = 75
WEIGHT_VARIANCE = 30
if len(sys.argv) < 5:
    print("Format: <host> <port> <device-id> <region> [<doppler-frequency-mean>] [<doppler-frequency-std>] [<pressure-mean>] [pressure-std]", sys.argv[0])
    exit(-1)

HOST = sys.argv[1]
PORT = int(sys.argv[2])
DEVICE_ID = sys.argv[3]
REGION = sys.argv[4]
DOPPLER_MEAN = sys.argv[5] if len(sys.argv) >= 6 else MEAN_FREQENCY
DOPPLER_VAR = sys.argv[6] if len(sys.argv) >= 7 else VARIANCE
PRESSURE_MEAN = sys.argv[7] if len(sys.argv) >= 8 else MEAN_WEIGHT
PRESSURE_VAR = sys.argv[8] if len(sys.argv) >= 9 else WEIGHT_VARIANCE
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((HOST, PORT))
    s.listen(1)
    while True:
        conn, addr = s.accept()
        print("Connected to: {}".format(addr))
        with conn:
            while True:
                try:
                    doppler_frequency = random.gauss(DOPPLER_MEAN, DOPPLER_VAR)
                    pressure = random.gauss(PRESSURE_MEAN, PRESSURE_VAR)
                    ir_sensor =  random.randint(0, 255)
                    data = "{},{},{},{:.2f},{},{},{:.2f},{},{},{}".format(int(time.time())*1000,f'mw{DEVICE_ID}',f'mw{REGION}',doppler_frequency,f'p{DEVICE_ID}',f'p{REGION}',pressure,f'ir{DEVICE_ID}',f'ir{REGION}',ir_sensor)
                    print(data+"\n")
                    conn.sendall("{}\n".format(data).encode('utf-8'))
                    time.sleep(1)
                except Exception as e:
                    print(e)
                    break