text:
#%%
from source.LL_functions import steady_LL_solve, plot_wake
from source.classes import EllipticalWing
import matplotlib.pyplot as plt
import numpy as np
# %matplotlib widget

def test_elliptical_wing():

    rho = 1.225

    # assemble elliptical wing
    span_b = 5.0
    c_root = 1.0
    u_flow = np.array([[0, -1.0, 0.1]])

    # EllipticalWing is a child class of LiftingSurface
    elliptical_wing = EllipticalWing(rt_chord=c_root,
                                     span=span_b,
                                     Re=1,
                                     afoil_name=[],
                                     nsegs=40,
                                     units='m')

    # redefine afoil polar table as idealised flat plate
    elliptical_wing.define_flat_plate_polar()

    # check plot looks OK
    elliptical_wing.plot2D()

    # assemble input dictionaries
    lifting_surface = [elliptical_wing.create_dict()]

    # do steady lifting line solve
    min_dt = c_root/np.linalg.norm(u_flow)
    out = steady_LL_solve(lifting_surface, u_flow, rho, dt=0.5, min_dt=min_dt, wake_rollup=False, include_shed_vorticity=True, nit=20, delta_visc=0.025)
    u_gamma = out[0]

    # compute lift coefficient given steady vortex solve
    u_cp = u_flow + u_gamma
    lift = elliptical_wing.LL_strip_theory_forces(u_cp, rho, full_output=False)
    V = np.linalg.norm(u_cp, axis=1).reshape(-1,1)
    cl = lift / (0.5 * rho * V ** 2 * elliptical_wing.dA)

    # compute theoretical values to compare to
    alpha_theory = np.arctan(0.1/1)
    AR = span_b ** 2 /(np.pi * span_b * c_root / 4)
    cl_theory = 2*np.pi/(1 + 2/AR)*alpha_theory

    fig = plt.figure()
    plt.plot(elliptical_wing.xcp[:,0], cl, 'k-')
    plt.plot([-span_b/2, span_b/2], [cl_theory, cl_theory])
    plt.grid(True)
    plt.xlabel("Span (m)")
    plt.ylabel("Lift coefficient (-)")
    plt.ylim([0.47, 0.48])
    plt.show()

    fig = plt.figure()
    ax = fig.gca(projection="3d")
    plot_wake(lifting_surface, out[3], out[5], ax=ax)

    assert any(np.isclose(cl, cl_theory, rtol=1e-03, atol=1e-03))

test_elliptical_wing()
# %%


text:
import decimal
import math
import operator

import numpy as np
import pandas as pd
import pandas.testing as tm
import pytest
from pytest import param

import ibis
from ibis import literal as L
from ibis.expr import datatypes as dt
from ibis.tests.util import assert_equal

try:
    import sqlalchemy as sa
except ImportError:
    sa = postgresql = mysql = None
else:
    from sqlalchemy.dialects import mysql, postgresql

@pytest.mark.parametrize(
    ('operand_fn', 'expected_operand_fn'),
    [
        param(lambda t: t.float_col, lambda t: t.float_col, id='float-column'),
        param(
            lambda t: t.double_col, lambda t: t.double_col, id='double-column'
        ),
        param(lambda t: ibis.literal(1.3), lambda t: 1.3, id='float-literal'),
        param(
            lambda t: ibis.literal(np.nan),
            lambda t: np.nan,
            id='nan-literal',
        ),
        param(
            lambda t: ibis.literal(np.inf),
            lambda t: np.inf,
            id='inf-literal',
        ),
        param(
            lambda t: ibis.literal(-np.inf),
            lambda t: -np.inf,
            id='-inf-literal',
        ),
    ],
)
@pytest.mark.parametrize(
    ('expr_fn', 'expected_expr_fn'),
    [
        param(operator.methodcaller('isnan'), np.isnan, id='isnan'),
        param(operator.methodcaller('isinf'), np.isinf, id='isinf'),
    ],
)
@pytest.mark.xfail_unsupported
def test_isnan_isinf(
    backend,
    con,
    alltypes,
    df,
    operand_fn,
    expected_operand_fn,
    expr_fn,
    expected_expr_fn,
):
    expr = expr_fn(operand_fn(alltypes))
    expected = expected_expr_fn(expected_operand_fn(df))

    result = con.execute(expr)

    if isinstance(expected, pd.Series):
        expected = backend.default_series_rename(expected)
        backend.assert_series_equal(result, expected)
    else:
        try:
            assert result == expected
        except ValueError:
            backend.assert_series_equal(result, expected)

@pytest.mark.parametrize(
    ('expr', 'expected'),
    [
        param(L(-5).abs(), 5, id='abs-neg'),
        param(L(5).abs(), 5, id='abs'),
        param(ibis.least(L(10), L(1)), 1, id='least'),
        param(ibis.greatest(L(10), L(1)), 10, id='greatest'),
        param(L(5.5).round(), 6.0, id='round'),
        param(L(5.556).round(2), 5.56, id='round-digits'),
        param(L(5.556).ceil(), 6.0, id='ceil'),
        param(L(5.556).floor(), 5.0, id='floor'),
        param(L(5.556).exp(), math.exp(5.556), id='expr'),
        param(L(5.556).sign(), 1, id='sign-pos'),
        param(L(-5.556).sign(), -1, id='sign-neg'),
        param(L(0).sign(), 0, id='sign-zero'),
        param(L(5.556).sqrt(), math.sqrt(5.556), id='sqrt'),
        param(L(5.556).log(2), math.log(5.556, 2), id='log-base'),
        param(L(5.556).ln(), math.log(5.556), id='ln'),
        param(L(5.556).log2(), math.log(5.556, 2), id='log2'),
        param(L(5.556).log10(), math.log10(5.556), id='log10'),
        param(L(5.556).radians(), math.radians(5.556), id='radians'),
        param(L(5.556).degrees(), math.degrees(5.556), id='degrees'),
        param(L(11) % 3, 11 % 3, id='mod'),
    ],
)
@pytest.mark.xfail_unsupported
def test_math_functions_literals(backend, con, alltypes, df, expr, expected):
    result = con.execute(expr)
    if isinstance(result, decimal.Decimal):
        # in case of Impala the result is decimal
        # >>> decimal.Decimal('5.56') == 5.56
        # False
        assert result == decimal.Decimal(str(expected))
    else:
        np.testing.assert_allclose(result, expected)

@pytest.mark.parametrize(
    ('expr_fn', 'expected_fn'),
    [
        param(
            lambda t: (-t.double_col).abs(),
            lambda t: (-t.double_col).abs(),
            id='abs-neg',
        ),
        param(
            lambda t: t.double_col.abs(),
            lambda t: t.double_col.abs(),
            id='abs',
        ),
        param(
            lambda t: t.double_col.ceil(),
            lambda t: np.ceil(t.double_col).astype('int64'),
            id='ceil',
        ),
        param(
            lambda t: t.double_col.floor(),
            lambda t: np.floor(t.double_col).astype('int64'),
            id='floor',
        ),
        param(
            lambda t: t.double_col.sign(),
            lambda t: np.sign(t.double_col),
            id='sign',
        ),
        param(
            lambda t: (-t.double_col).sign(),
            lambda t: np.sign(-t.double_col),
            id='sign-negative',
        ),
    ],
)
@pytest.mark.xfail_unsupported
def test_simple_math_functions_columns(
    backend, con, alltypes, df, expr_fn, expected_fn
):
    expr = expr_fn(alltypes)
    expected = backend.default_series_rename(expected_fn(df))
    result = con.execute(expr)
    backend.assert_series_equal(result, expected)

# we add one to double_col in this test to make sure the common case works (no
# domain errors), and we test the backends' various failure modes in each
# backend's test suite

@pytest.mark.parametrize(
    ('expr_fn', 'expected_fn'),
    [
        param(
            lambda t: t.double_col.add(1).sqrt(),
            lambda t: np.sqrt(t.double_col + 1),
            id='sqrt',
        ),
        param(
            lambda t: t.double_col.add(1).exp(),
            lambda t: np.exp(t.double_col + 1),
            id='exp',
        ),
        param(
            lambda t: t.double_col.add(1).log(2),
            lambda t: np.log2(t.double_col + 1),
            id='log2',
        ),
        param(
            lambda t: t.double_col.add(1).ln(),
            lambda t: np.log(t.double_col + 1),
            id='ln',
        ),
        param(
            lambda t: t.double_col.add(1).log10(),
            lambda t: np.log10(t.double_col + 1),
            id='log10',
        ),
    ],
)
@pytest.mark.xfail_unsupported
def test_complex_math_functions_columns(
    backend, con, alltypes, df, expr_fn, expected_fn
):
    expr = expr_fn(alltypes)
    expected = backend.default_series_rename(expected_fn(df))
    result = con.execute(expr)
    backend.assert_series_equal(result, expected)

@pytest.mark.parametrize(
    ('expr_fn', 'expected_fn'),
    [
        param(
            lambda be, t: t.double_col.round(),
            lambda be, t: be.round(t.double_col),
            id='round',
        ),
        param(
            lambda be, t: t.double_col.add(0.05).round(3),
            lambda be, t: be.round(t.double_col + 0.05, 3),
            id='round-with-param',
        ),
        param(
            lambda be, t: be.least(ibis.least, t.bigint_col, t.int_col),
            lambda be, t: pd.Series(list(map(min, t.bigint_col, t.int_col))),
            id='least-all-columns',
        ),
        param(
            lambda be, t: be.least(ibis.least, t.bigint_col, t.int_col, -2),
            lambda be, t: pd.Series(
                list(map(min, t.bigint_col, t.int_col, [-2] * len(t)))
            ),
            id='least-scalar',
        ),
        param(
            lambda be, t: be.greatest(ibis.greatest, t.bigint_col, t.int_col),
            lambda be, t: pd.Series(list(map(max, t.bigint_col, t.int_col))),
            id='greatest-all-columns',
        ),
        param(
            lambda be, t: be.greatest(
                ibis.greatest, t.bigint_col, t.int_col, -2
            ),
            lambda be, t: pd.Series(
                list(map(max, t.bigint_col, t.int_col, [-2] * len(t)))
            ),
            id='greatest-scalar',
        ),
    ],
)
@pytest.mark.xfail_unsupported
def test_backend_specific_numerics(
    backend, con, df, alltypes, expr_fn, expected_fn
):
    expr = expr_fn(backend, alltypes)
    result = backend.default_series_rename(con.execute(expr))
    expected = backend.default_series_rename(expected_fn(backend, df))
    backend.assert_series_equal(result, expected)

@pytest.mark.parametrize(
    'op',
    [
        operator.add,
        operator.sub,
        operator.mul,
        operator.truediv,
        operator.floordiv,
        operator.pow,
    ],
    ids=lambda op: op.__name__,
)
@pytest.mark.xfail_unsupported
def test_binary_arithmetic_operations(backend, alltypes, df, op):
    smallint_col = alltypes.smallint_col + 1  # make it nonzero
    smallint_series = df.smallint_col + 1

    expr = op(alltypes.double_col, smallint_col)

    result = expr.execute()
    expected = op(df.double_col, smallint_series)
    if op is operator.floordiv:
        # defined in ops.FloorDivide.output_type
        # -> returns int64 whereas pandas float64
        result = result.astype('float64')

    expected = backend.default_series_rename(expected)
    backend.assert_series_equal(result, expected, check_exact=False)

def test_mod(backend, alltypes, df):
    expr = operator.mod(alltypes.smallint_col, alltypes.smallint_col + 1)

    result = expr.execute()
    expected = operator.mod(df.smallint_col, df.smallint_col + 1)

    expected = backend.default_series_rename(expected)
    backend.assert_series_equal(result, expected, check_dtype=False)

def test_floating_mod(backend, alltypes, df):
    if not backend.supports_floating_modulus:
        pytest.skip(f'{backend} does not support floating modulus operation')
    expr = operator.mod(alltypes.double_col, alltypes.smallint_col + 1)

    result = expr.execute()
    expected = operator.mod(df.double_col, df.smallint_col + 1)

    expected = backend.default_series_rename(expected)
    backend.assert_series_equal(result, expected, check_exact=False)

@pytest.mark.parametrize(
    'column',
    [
        'tinyint_col',
        'smallint_col',
        'int_col',
        'bigint_col',
        'float_col',
        'double_col',
    ],
)
@pytest.mark.parametrize('denominator', [0, 0.0])
def test_divide_by_zero(backend, alltypes, df, column, denominator):
    if not backend.supports_divide_by_zero:
        pytest.skip(f'{backend} does not support safe division by zero')
    expr = alltypes[column] / denominator
    expected = backend.default_series_rename(df[column].div(denominator))
    result = expr.execute()
    backend.assert_series_equal(result, expected)

@pytest.mark.skipif(
    sa is None, reason="Tests available for sqlalchemy based backend"
)
@pytest.mark.parametrize(
    'dialects, default_precisions, default_scales',
    [
        (
            {'postgres': postgresql, 'mysql': mysql},
            {'postgres': 1000, 'mysql': 10},
            {'postgres': 0, 'mysql': 0},
        )
    ],
)
@pytest.mark.only_on_backends(['postgres', 'mysql'])
def test_sa_default_numeric_precision_and_scale(
    con, backend, dialects, default_precisions, default_scales
):
    # TODO: find a better way to access ibis.sql.alchemy
    from ibis.backends.base.sql.alchemy import schema_from_table

    dialect = dialects[backend.name()]
    default_precision = default_precisions[backend.name()]
    default_scale = default_scales[backend.name()]

    typespec = [
        # name, sqlalchemy type, ibis type
        ('n1', dialect.NUMERIC, dt.Decimal(default_precision, default_scale)),
        ('n2', dialect.NUMERIC(5), dt.Decimal(5, default_scale)),
        ('n3', dialect.NUMERIC(None, 4), dt.Decimal(default_precision, 4)),
        ('n4', dialect.NUMERIC(10, 2), dt.Decimal(10, 2)),
    ]

    sqla_types = []
    ibis_types = []
    for name, t, ibis_type in typespec:
        sqla_type = sa.Column(name, t, nullable=True)
        sqla_types.append(sqla_type)
        ibis_types.append((name, ibis_type(nullable=True)))

    # Create a table with the numeric types.
    table_name = 'test_sa_default_param_decimal'
    engine = con.con
    table = sa.Table(table_name, sa.MetaData(bind=engine), *sqla_types)

    # Check that we can correctly recover the default precision and scale.
    schema = schema_from_table(table)
    expected = ibis.schema(ibis_types)

    assert_equal(schema, expected)
    con.drop_table(table_name, force=True)

@pytest.mark.only_on_backends(['postgres', 'mysql'])
def test_random(con):
    expr = ibis.random()
    result = con.execute(expr)
    assert isinstance(result, float)
    assert 0 <= result < 1

    # Ensure a different random number of produced on subsequent calls
    result2 = con.execute(expr)
    assert isinstance(result2, float)
    assert 0 <= result2 < 1
    assert result != result2

@pytest.mark.only_on_backends(['pandas', 'dask', 'pyspark'])
@pytest.mark.xfail_unsupported
@pytest.mark.parametrize(
    ('ibis_func', 'pandas_func'),
    [
        (lambda x: x.clip(lower=0), lambda x: x.clip(lower=0)),
        (lambda x: x.clip(lower=0.0), lambda x: x.clip(lower=0.0)),
        (lambda x: x.clip(upper=0), lambda x: x.clip(upper=0)),
        (
            lambda x: x.clip(lower=x - 1, upper=x + 1),
            lambda x: x.clip(lower=x - 1, upper=x + 1),
        ),
        (
            lambda x: x.clip(lower=0, upper=1),
            lambda x: x.clip(lower=0, upper=1),
        ),
        (
            lambda x: x.clip(lower=0, upper=1.0),
            lambda x: x.clip(lower=0, upper=1.0),
        ),
    ],
)
def test_clip(alltypes, df, ibis_func, pandas_func):
    result = ibis_func(alltypes.int_col).execute()
    expected = pandas_func(df.int_col).astype(result.dtype)
    # Names won't match in the Pyspark backend since Pyspark
    # gives 'tmp' name when executing a ColumnExpr
    tm.assert_series_equal(result, expected, check_names=False)

@pytest.mark.skip_backends(
    [
        'pandas',
        'dask',
        'csv',
        'datafusion',
        'pyspark',
        'clickhouse',
    ]
)
def test_histogram(con, alltypes):
    n = 10
    results = con.execute(alltypes.int_col.histogram(n))
    assert len(results.value_counts()) == n

ext: py

max_stars_repo_name: EdAbati/ibis

max_issues_repo_name: EdAbati/ibis

max_forks_repo_name: EdAbati/ibis

reason: import numpy


text:
from pathlib import Path
from typing import List, Dict, Any
from typing import Tuple

import albumentations as albu
import numpy as np
import torch
from iglovikov_helper_functions.utils.image_utils import load_rgb, load_grayscale
from pytorch_toolbelt.utils.torch_utils import image_to_tensor
from torch.utils.data import Dataset

class SegmentationDataset(Dataset):
    def __init__(
        self,
        samples: List[Tuple[Path, Path]],
        transform: albu.Compose,
        deg_transform: albu.Compose = None,
        length: int = None,
    ) -> None:
        self.samples = samples
        self.transform = transform
        self.deg_transform = deg_transform

        if length is None:
            self.length = len(self.samples)
        else:
            self.length = length

    def __len__(self) -> int:
        return self.length

    def __getitem__(self, idx: int) -> Dict[str, Any]:
        idx = idx % len(self.samples)

        image_path, mask_path = self.samples[idx]

        image = load_rgb(image_path, lib="cv2")
        mask = load_grayscale(mask_path)

        # apply augmentations
        sample = self.transform(image=image, mask=mask)
        image, mask = sample["image"], sample["mask"]
        if self.deg_transform is not None:
            degraded_sample = self.deg_transform(image=image, mask=mask)
            degraded_image, degraded_mask = degraded_sample["image"], degraded_sample["mask"]
        else:
            degraded_image = image
            degraded_mask = mask

        degraded_mask = torch.from_numpy(degraded_mask)
        mask = torch.from_numpy(mask)
        return {
            "image_id": image_path.stem,
            "features": image_to_tensor(degraded_image),
            "masks": torch.unsqueeze(degraded_mask, 0).float(),
            "features_HQ": image_to_tensor(image) / 255.,
            "mask_HQ": torch.unsqueeze(mask, 0).float(),
        }


text:
from __future__ import division, print_function
# coding = utf8
import sys
import os
import glob
import re
import numpy as np
import time

# Keras utils
import tensorflow as tf
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image

# Flask utils
from flask import Flask, render_template, url_for, request, redirect
from werkzeug.utils import secure_filename
from gevent.pywsgi import WSGIServer

# Define a flask app
app = Flask(__name__)

# Model saved with Keras.save()
#MODEL_PATH='./model/custom_cnn_lenet_val_9539_oct_24_1100.h5'
#MODEL_PATH='./model/VGG_94.52_11102020_8 49.h5'

MODEL_PATH = './model/model.h5'
input_size=(100,100)

model = load_model(MODEL_PATH)
probability = 0.3

def model_predict(img_path,model_path,input_size):

    img = image.load_img(img_path,target_size=input_size)
    img_array = image.img_to_array(img)
    img_array = np.expand_dims(img_array,axis=0) # changes input shape to a tensor (1,160,160,3)
    #img_array = preprocess_input(img_array) # preprocess input based on mobilenet_v2 conventions

    output = model.predict(img_array).flatten()
    prediction = output[0]

    return prediction

@app.route('/', methods=['GET'])
def index():
    # displays main page
    return render_template('index.html')

@app.route('/predict',methods=['GET','POST'])
def upload():
    if request.method == 'POST':
        # Get the file from post request
        f = request.files['file']

        # Save the file to ./uploads
        basepath = os.path.dirname(__file__)

        # Append timestamp to ensure unique filename
        file_path = os.path.join(
            basepath, 'uploads', secure_filename(f.filename + str(int(time.time()))))
        f.save(file_path)

        # Make prediction
        prediction = model_predict(file_path, MODEL_PATH, input_size)

        # Process your result for human
        # Preserve the 0- and 1- prefixes
        if prediction <= probability:
            result = f"1-The Image looks Parasitized.\nThe probability that the blood smear is uninfected is {prediction:.3} "
        else:
            result=f"0-The Image looks Uninfected.\nThe probability that the blood smear is uninfected is {prediction:.3} "

        # Delete the file
        os.remove(file_path)

        return result
    return None

if __name__ == '__main__':
    app.run(debug=True)

max_stars_repo_name: TheReconPilot/IISER-Pune-India


text:
import torch
import torch.nn.functional as F
import numpy as np
from model import FcNet

from matching.pfnm import layer_group_descent as pdm_multilayer_group_descent
from matching.pfnm_communication import layer_group_descent as pdm_iterative_layer_group_descent
from matching.pfnm_communication import build_init as pdm_build_init

from itertools import product
from sklearn.metrics import confusion_matrix

def prepare_weight_matrix(n_classes, weights: dict):
    weights_list = {}

    for net_i, cls_cnts in weights.items():
        cls = np.array(list(cls_cnts.keys()))
        cnts = np.array(list(cls_cnts.values()))
        weights_list[net_i] = np.array([0] * n_classes, dtype=np.float32)
        weights_list[net_i][cls] = cnts
        weights_list[net_i] = torch.from_numpy(weights_list[net_i]).view(1, -1)

    return weights_list

def prepare_uniform_weights(n_classes, net_cnt, fill_val=1):
    weights_list = {}

    for net_i in range(net_cnt):
        temp = np.array([fill_val] * n_classes, dtype=np.float32)
        weights_list[net_i] = torch.from_numpy(temp).view(1, -1)

    return weights_list

def prepare_sanity_weights(n_classes, net_cnt):
    return prepare_uniform_weights(n_classes, net_cnt, fill_val=0)

def normalize_weights(weights):
    Z = np.array([])
    eps = 1e-6
    weights_norm = {}

    for _, weight in weights.items():
        if len(Z) == 0:
            Z = weight.data.numpy()
        else:
            Z = Z + weight.data.numpy()

    for mi, weight in weights.items():
        weights_norm[mi] = weight / torch.from_numpy(Z + eps)

    return weights_norm

def get_weighted_average_pred(models: list, weights: dict, x):
    out_weighted = None

    # Compute the predictions
    for model_i, model in enumerate(models):
        out = F.softmax(model(x), dim=-1)  # (N, C)

        if out_weighted is None:
            out_weighted = (out * weights[model_i])
        else:
            out_weighted += (out * weights[model_i])

    return out_weighted

def compute_ensemble_accuracy(models: list, dataloader, n_classes, train_cls_counts=None, uniform_weights=False, sanity_weights=False):

    correct, total = 0, 0
    true_labels_list, pred_labels_list = np.array([]), np.array([])

    was_training = [False]*len(models)
    for i, model in enumerate(models):
        if model.training:
            was_training[i] = True
            model.eval()

    if uniform_weights is True:
        weights_list = prepare_uniform_weights(n_classes, len(models))
    elif sanity_weights is True:
        weights_list = prepare_sanity_weights(n_classes, len(models))
    else:
        weights_list = prepare_weight_matrix(n_classes, train_cls_counts)

    weights_norm = normalize_weights(weights_list)

    with torch.no_grad():
        for batch_idx, (x, target) in enumerate(dataloader):
            target = target.long()
            out = get_weighted_average_pred(models, weights_norm, x)

            _, pred_label = torch.max(out, 1)

            total += x.data.size()[0]
            correct += (pred_label == target.data).sum().item()

            pred_labels_list = np.append(pred_labels_list, pred_label.numpy())
            true_labels_list = np.append(true_labels_list, target.data.numpy())

    print(correct, total)

    conf_matrix = confusion_matrix(true_labels_list, pred_labels_list)

    for i, model in enumerate(models):
        if was_training[i]:
            model.train()

    return correct / float(total), conf_matrix

def pdm_prepare_weights(nets):
    weights = []

    for net_i, net in enumerate(nets):
        layer_i = 0
        statedict = net.state_dict()
        net_weights = []
        while True:

            if ('layers.%d.weight' % layer_i) not in statedict.keys():
                break

            layer_weight = statedict['layers.%d.weight' % layer_i].numpy().T
            layer_bias = statedict['layers.%d.bias' % layer_i].numpy()

            net_weights.extend([layer_weight, layer_bias])
            layer_i += 1

        weights.append(net_weights)

    return weights

def pdm_prepare_freq(cls_freqs, n_classes):
    freqs = []

    for net_i in sorted(cls_freqs.keys()):
        net_freqs = [0] * n_classes

        for cls_i in cls_freqs[net_i]:
            net_freqs[cls_i] = cls_freqs[net_i][cls_i]

        freqs.append(np.array(net_freqs))

    return freqs

def compute_pdm_net_accuracy(weights, train_dl, test_dl, n_classes):

    dims = []
    dims.append(weights[0].shape[0])

    for i in range(0, len(weights), 2):
        dims.append(weights[i].shape[1])

    ip_dim = dims[0]
    op_dim = dims[-1]
    hidden_dims = dims[1:-1]

    pdm_net = FcNet(ip_dim, hidden_dims, op_dim)
    statedict = pdm_net.state_dict()

    # print(pdm_net)

    i = 0
    layer_i = 0
    while i < len(weights):
        weight = weights[i]
        i += 1
        bias = weights[i]
        i += 1

        statedict['layers.%d.weight' % layer_i] = torch.from_numpy(weight.T)
        statedict['layers.%d.bias' % layer_i] = torch.from_numpy(bias)
        layer_i += 1

    pdm_net.load_state_dict(statedict)

    train_acc, conf_matrix_train = compute_ensemble_accuracy([pdm_net], train_dl, n_classes, uniform_weights=True)
    test_acc, conf_matrix_test = compute_ensemble_accuracy([pdm_net], test_dl, n_classes, uniform_weights=True)

    return train_acc, test_acc, conf_matrix_train, conf_matrix_test

def compute_pdm_matching_multilayer(models, train_dl, test_dl, cls_freqs, n_classes, sigma0=None, it=0, sigma=None, gamma=None):
    batch_weights = pdm_prepare_weights(models)
    batch_freqs = pdm_prepare_freq(cls_freqs, n_classes)
    res = {}
    best_test_acc, best_train_acc, best_weights, best_sigma, best_gamma, best_sigma0 = -1, -1, None, -1, -1, -1

    gammas = [1.0, 1e-3, 50.0] if gamma is None else [gamma]
    sigmas = [1.0, 0.1, 0.5] if sigma is None else [sigma]
    sigma0s = [1.0, 10.0] if sigma0 is None else [sigma0]

    for gamma, sigma, sigma0 in product(gammas, sigmas, sigma0s):
        print("Gamma: ", gamma, "Sigma: ", sigma, "Sigma0: ", sigma0)

        hungarian_weights = pdm_multilayer_group_descent(
            batch_weights, sigma0_layers=sigma0, sigma_layers=sigma, batch_frequencies=batch_freqs, it=it, gamma_layers=gamma
        )

        train_acc, test_acc, _, _ = compute_pdm_net_accuracy(hungarian_weights, train_dl, test_dl, n_classes)

        key = (sigma0, sigma, gamma)
        res[key] = {}
        res[key]['shapes'] = list(map(lambda x: x.shape, hungarian_weights))
        res[key]['train_accuracy'] = train_acc
        res[key]['test_accuracy'] = test_acc

        print('Sigma0: %s. Sigma: %s. Shapes: %s, Accuracy: %f' % (
        str(sigma0), str(sigma), str(res[key]['shapes']), test_acc))

        if train_acc > best_train_acc:
            best_test_acc = test_acc
            best_train_acc = train_acc
            best_weights = hungarian_weights
            best_sigma = sigma
            best_gamma = gamma
            best_sigma0 = sigma0

    print('Best sigma0: %f, Best sigma: %f, Best Gamma: %f, Best accuracy (Test): %f. Training acc: %f' % (
    best_sigma0, best_sigma, best_gamma, best_test_acc, best_train_acc))

    return (best_sigma0, best_sigma, best_gamma, best_test_acc, best_train_acc, best_weights, res)

def compute_iterative_pdm_matching(models, train_dl, test_dl, cls_freqs, n_classes, sigma, sigma0, gamma, it, old_assignment=None):

    batch_weights = pdm_prepare_weights(models)
    batch_freqs = pdm_prepare_freq(cls_freqs, n_classes)

    hungarian_weights, assignments = pdm_iterative_layer_group_descent(
        batch_weights, batch_freqs, sigma_layers=sigma, sigma0_layers=sigma0, gamma_layers=gamma, it=it, assignments_old=old_assignment
    )

    train_acc, test_acc, conf_matrix_train, conf_matrix_test = compute_pdm_net_accuracy(hungarian_weights, train_dl, test_dl, n_classes)

    batch_weights_new = [pdm_build_init(hungarian_weights, assignments, j) for j in range(len(models))]
    matched_net_shapes = list(map(lambda x: x.shape, hungarian_weights))

    return batch_weights_new, train_acc, test_acc, matched_net_shapes, assignments, hungarian_weights, conf_matrix_train, conf_matrix_test

def flatten_weights(weights_j):
    flat_weights = np.hstack((weights_j[0].T, weights_j[1].reshape(-1,1), weights_j[2]))
    return flat_weights

def build_network(clusters, batch_weights, D):
    cluster_network = [clusters[:,:D].T, clusters[:,D].T, clusters[:,(D+1):]]
    bias = np.mean(batch_weights, axis=0)[-1]
    cluster_network += [bias]
    return cluster_network