<commit_before>import numpy as np
import theano
import lasagne as L
import time
from scipy.stats import bayes_mvs as bmvs
from loading import augment
from network import Network

T = theano.tensor

class Trainer(object):
    """
    Base for subclassing optimizers
    """
    def __init__(self, batchsize=128, stopthresh=100, print_interval=50,
                updates=L.updates.adam, update_args={}, seed=None):
        """
        Move relevant items into arguments later
        Fix updates to get set on network
        """
        self.updates = updates
        self.bs = batchsize
        self.epoch = 0
        self.max_epoch = 5000
        self.stopthresh = stopthresh
        self.print_interval = print_interval
        self.update_args = update_args
        self.seed = seed
        if self.seed is not None:
            np.random.seed(self.seed)

    def train(self, network, training_data, validation_data):
        """
        Training and validation
        It might be better to abstract the training and validation loops into
        their own functions, but not a priority for now
        """
        network.updates = self.updates(network.loss, network.params, **self.update_args)
        X, y = training_data
        Xv, yv = validation_data
        self.train_start = time.time()

        for epoch in range(self.max_epoch):
            train_err = 0
            train_bats = 0
            val_err = 0
            val_acc = 0
            val_bats = 0
            epoch_start = time.time()

            for batch in self.iterate_minibatches(X, y, shuffle=True):
                inputs, targets = batch
                train_err += network.train_fn(inputs, targets)
                train_bats += 1

            epoch_dur = time.time() - epoch_start

            for batch in self.iterate_minibatches(Xv, yv, shuffle=False):
                inputs, targets = batch
                error, accuracy = network.test_fn(inputs, targets)
                val_err += error
                val_acc += accuracy
                val_bats += 1

            network.train_err = train_err / train_bats
            network.val_err = val_err / val_bats
            network.update_traces()

            self.epoch = epoch
            del_val_err = np.diff(network.val_trace)
            if epoch > self.stopthresh:
                if del_val_err[epoch-self.stopthresh:epoch].mean() > 0:
                    print("Abandon ship!")
                    break

            if epoch % self.print_interval == 0:
                print("Epoch {} took {:.3f}s".format(epoch, epoch_dur))
                print("\ttraining loss:\t\t\t{:.4f}".format(train_err/train_bats))
                print("\tvalidation loss:\t\t{:.4f}".format(val_err/val_bats))
                print("\tvalidation accuracy:\t\t{:.2f}%".format(100*val_acc/val_bats))
                print("\ttotal time elapsed:\t\t{:.3f}s".format(time.time() - self.train_start))

        return train_err, val_err

    def test(self, network, testing_data):
        X, y = testing_data
        test_err = 0
        test_acc = 0
        test_bats = 0

        for batch in self.iterate_minibatches(X, y, shuffle=False):
            inputs, targets = batch
            error, accuracy = network.test_fn(inputs, targets)
            test_err += error
            test_acc += accuracy
            test_bats += 1

        network.test_err = test_err/test_bats
        print("\nTEST PERFORMANCE")
        print("\tStopped in epoch:\t\t{}".format(self.epoch))
        print("\tTest loss:\t\t\t{:.4f}".format(test_err/test_bats))
        print("\tTest accuracy:\t\t\t{:.2f}%\n".format(100*test_acc/test_bats))

        return test_err, test_acc, test_bats

    def iterate_minibatches(self, inputs, targets, shuffle=False):
        assert len(inputs) == len(targets)
        if shuffle:
            idxs = np.arange(len(inputs))
            np.random.shuffle(idxs)

        for idx in range(0, len(inputs)-self.bs+1, self.bs):
            if shuffle:
                excerpt = idxs[idx:idx+self.bs]
            else:
                excerpt = slice(idx, idx+self.bs)
            yield inputs[excerpt], targets[excerpt]

class DefaultTrainer(Trainer):
    """
    Implements an additional function that does training for all 5 default
    cross-validation splits

    This is meant as a standalone, not for subclassing. But I should consider
    implementing a basic train_all function that does random cv splits rather
    than premade...

    self.train_all may be further decomposable -
    eg separate "unpack data" function...

    Automatic parameter saving to be implemented later...
    """

    def run_split(self, architecture, data, split, augment_fn):
        print("\nSplit Number {}".format(split))
        D, groups, Xs, ys, Ss = data
        num_splits = len(Xs)
        r = np.tile(np.arange(num_splits), [num_splits, 1])
        r = (r + r.T) % num_splits

        net = Network(architecture)
        train_idxs = r[split, :3]
        val_idxs = r[split, 3:4]
        test_idxs = r[split, 4:]

        X, y, S = [np.concatenate(np.array(Z)[train_idxs]) for Z in [Xs, ys, Ss]]
        Xv, yv, Sv = [np.concatenate(np.array(Z)[val_idxs]) for Z in [Xs, ys, Ss]]
        Xt, yt, St = [np.concatenate(np.array(Z)[test_idxs]) for Z in [Xs, ys, Ss]]
        X, y = augment_fn((X, y))
        S = np.concatenate([S, S, S, S])
        print(Xt.shape)

        self.train(net, training_data=(X, y), validation_data=(Xv, yv))
        self.test(net, testing_data=(Xt, yt))

        return net

    def train_all(self, architecture, data, seed=None, save_params=False, augment_fn=augment):
        net_list = []
        if seed:
            np.random.seed(seed)

        starttime = time.time()
        num_splits = len(data[2])
        for split in range(num_splits):
            net = self.run_split(architecture, data, split, augment_fn)
            net_list.append(net)

        mvs = bmvs([n.test_err for n in net_list ], alpha=.95)
        time_elapsed = time.time() - starttime
        print("\n\nOVERALL RESULTS")
        print("\tAverage NLL:\t\t{:.3f}".format(mvs[0][0]))
        print("\tCred. Interval:\t\t[{:.3f}, {:.3f}]".format(mvs[0][1][0], mvs[0][1][1]))
        print("\tTotal time:\t\t{:.2f}".format(time_elapsed))

        return net_list

class FineTuner(DefaultTrainer):
    """
    Trainer to fine tune networks to individual subjects

    Consider moving freeze, param set functions properly into Network object
    Abstracting split functions and augment in DefaultTrainer would be good too
    """

    def train_all(self, architecture, data, split, seed=None,
                    startparams=None, freeze=True, exclude=[-4]):
        if seed:
            np.random.seed(seed)

        D, groups, Xs, ys, Ss = data
        num_splits = len(Xs)
        r = np.tile(np.arange(num_splits), [num_splits, 1])
        r = (r + r.T) % num_splits

        starttime = time.time()
        net = Network(architecture)
        if startparams:
            _layers = L.layers.get_all_layers(net.net)
            L.layers.set_all_param_values(_layers, startparams)
            # convlayer, prelulayer = _layers[1:3]
            if freeze:
                net.freeze_params(exclude=exclude)
                # convlayer.params[convlayer.W].remove('trainable')
                # convlayer.params[convlayer.b].remove('trainable')
                # prelulayer.params[prelulayer.alpha].remove('trainable')

        train_idxs = r[split, :3]
        val_idxs = r[split, 3:4]
        test_idxs = r[split, 4:]

        X, y, S = [np.concatenate(np.array(Z)[train_idxs]) for Z in [Xs, ys, Ss]]
        Xv, yv, Sv = [np.concatenate(np.array(Z)[val_idxs]) for Z in [Xs, ys, Ss]]
        Xt, yt, St = [np.concatenate(np.array(Z)[test_idxs]) for Z in [Xs, ys, Ss]]
        X, y = augment((X, y))
        S = np.concatenate([S, S, S, S])
        self.train(net, training_data=(X, y), validation_data=(Xv, yv))
        self.test(net, testing_data=(Xt, yt))
        time_elapsed = time.time() - starttime

        return net

def run_full_fit(arch, archname):
    """
    Runs the full fitting experiment,
    pretraining on later experiments and testing on first.

    Saves data as it goes to avoid eating memory.
    """

    # start training
    trainer = DefaultTrainer(stopthresh=75, print_interval=20)
    net_list = trainer.train_all(architecture=arch, data=data, seed=985227)

    # save params
    for i, n in enumerate(net_list):
        fname = '{} {} split agg fit exp 1-4'.format(archname, i)
        n.save_params(os.path.join(paramsdir, fname))

    tuner = FineTuner(stopthresh=20)
    for i, n in enumerate(net_list):
        for j in range(5):
            fname = '{} {} agg fit exp 1-4 {} tune fit exp 0'.format(archname, i, j)
            params = L.get_all_param_values(n.net)
            net = tuner.train_all(
                architecture=arch, data=hvhdata,
                split=j, startparams=params, freeze=True
            )
            net.save_params(os.path.join(paramsdir, fname))

    return None
<commit_msg>remove old freeze lines<commit_after>import numpy as np
import theano
import lasagne as L
import time
from scipy.stats import bayes_mvs as bmvs
from loading import augment
from network import Network

T = theano.tensor

class Trainer(object):
    """
    Base for subclassing optimizers
    """
    def __init__(self, batchsize=128, stopthresh=100, print_interval=50,
                updates=L.updates.adam, update_args={}, seed=None):
        """
        Move relevant items into arguments later
        Fix updates to get set on network
        """
        self.updates = updates
        self.bs = batchsize
        self.epoch = 0
        self.max_epoch = 5000
        self.stopthresh = stopthresh
        self.print_interval = print_interval
        self.update_args = update_args
        self.seed = seed
        if self.seed is not None:
            np.random.seed(self.seed)

    def train(self, network, training_data, validation_data):
        """
        Training and validation
        It might be better to abstract the training and validation loops into
        their own functions, but not a priority for now
        """
        network.updates = self.updates(network.loss, network.params, **self.update_args)
        X, y = training_data
        Xv, yv = validation_data
        self.train_start = time.time()

        for epoch in range(self.max_epoch):
            train_err = 0
            train_bats = 0
            val_err = 0
            val_acc = 0
            val_bats = 0
            epoch_start = time.time()

            for batch in self.iterate_minibatches(X, y, shuffle=True):
                inputs, targets = batch
                train_err += network.train_fn(inputs, targets)
                train_bats += 1

            epoch_dur = time.time() - epoch_start

            for batch in self.iterate_minibatches(Xv, yv, shuffle=False):
                inputs, targets = batch
                error, accuracy = network.test_fn(inputs, targets)
                val_err += error
                val_acc += accuracy
                val_bats += 1

            network.train_err = train_err / train_bats
            network.val_err = val_err / val_bats
            network.update_traces()

            self.epoch = epoch
            del_val_err = np.diff(network.val_trace)
            if epoch > self.stopthresh:
                if del_val_err[epoch-self.stopthresh:epoch].mean() > 0:
                    print("Abandon ship!")
                    break

            if epoch % self.print_interval == 0:
                print("Epoch {} took {:.3f}s".format(epoch, epoch_dur))
                print("\ttraining loss:\t\t\t{:.4f}".format(train_err/train_bats))
                print("\tvalidation loss:\t\t{:.4f}".format(val_err/val_bats))
                print("\tvalidation accuracy:\t\t{:.2f}%".format(100*val_acc/val_bats))
                print("\ttotal time elapsed:\t\t{:.3f}s".format(time.time() - self.train_start))

        return train_err, val_err

    def test(self, network, testing_data):
        X, y = testing_data
        test_err = 0
        test_acc = 0
        test_bats = 0

        for batch in self.iterate_minibatches(X, y, shuffle=False):
            inputs, targets = batch
            error, accuracy = network.test_fn(inputs, targets)
            test_err += error
            test_acc += accuracy
            test_bats += 1

        network.test_err = test_err/test_bats
        print("\nTEST PERFORMANCE")
        print("\tStopped in epoch:\t\t{}".format(self.epoch))
        print("\tTest loss:\t\t\t{:.4f}".format(test_err/test_bats))
        print("\tTest accuracy:\t\t\t{:.2f}%\n".format(100*test_acc/test_bats))

        return test_err, test_acc, test_bats

    def iterate_minibatches(self, inputs, targets, shuffle=False):
        assert len(inputs) == len(targets)
        if shuffle:
            idxs = np.arange(len(inputs))
            np.random.shuffle(idxs)

        for idx in range(0, len(inputs)-self.bs+1, self.bs):
            if shuffle:
                excerpt = idxs[idx:idx+self.bs]
            else:
                excerpt = slice(idx, idx+self.bs)
            yield inputs[excerpt], targets[excerpt]

class DefaultTrainer(Trainer):
    """
    Implements an additional function that does training for all 5 default
    cross-validation splits

    This is meant as a standalone, not for subclassing. But I should consider
    implementing a basic train_all function that does random cv splits rather
    than premade...

    self.train_all may be further decomposable -
    eg separate "unpack data" function...

    Automatic parameter saving to be implemented later...
    """

    def run_split(self, architecture, data, split, augment_fn):
        print("\nSplit Number {}".format(split))
        D, groups, Xs, ys, Ss = data
        num_splits = len(Xs)
        r = np.tile(np.arange(num_splits), [num_splits, 1])
        r = (r + r.T) % num_splits

        net = Network(architecture)
        train_idxs = r[split, :3]
        val_idxs = r[split, 3:4]
        test_idxs = r[split, 4:]

        X, y, S = [np.concatenate(np.array(Z)[train_idxs]) for Z in [Xs, ys, Ss]]
        Xv, yv, Sv = [np.concatenate(np.array(Z)[val_idxs]) for Z in [Xs, ys, Ss]]
        Xt, yt, St = [np.concatenate(np.array(Z)[test_idxs]) for Z in [Xs, ys, Ss]]
        X, y = augment_fn((X, y))
        S = np.concatenate([S, S, S, S])
        print(Xt.shape)

        self.train(net, training_data=(X, y), validation_data=(Xv, yv))
        self.test(net, testing_data=(Xt, yt))

        return net

    def train_all(self, architecture, data, seed=None, save_params=False, augment_fn=augment):
        net_list = []
        if seed:
            np.random.seed(seed)

        starttime = time.time()
        num_splits = len(data[2])
        for split in range(num_splits):
            net = self.run_split(architecture, data, split, augment_fn)
            net_list.append(net)

        mvs = bmvs([n.test_err for n in net_list ], alpha=.95)
        time_elapsed = time.time() - starttime
        print("\n\nOVERALL RESULTS")
        print("\tAverage NLL:\t\t{:.3f}".format(mvs[0][0]))
        print("\tCred. Interval:\t\t[{:.3f}, {:.3f}]".format(mvs[0][1][0], mvs[0][1][1]))
        print("\tTotal time:\t\t{:.2f}".format(time_elapsed))

        return net_list

class FineTuner(DefaultTrainer):
    """
    Trainer to fine tune networks to individual subjects

    Consider moving freeze, param set functions properly into Network object
    Abstracting split functions and augment in DefaultTrainer would be good too
    """

    def train_all(self, architecture, data, split, seed=None,
                    startparams=None, freeze=True, exclude=[-4]):
        if seed:
            np.random.seed(seed)

        D, groups, Xs, ys, Ss = data
        num_splits = len(Xs)
        r = np.tile(np.arange(num_splits), [num_splits, 1])
        r = (r + r.T) % num_splits

        starttime = time.time()
        net = Network(architecture)
        if startparams:
            _layers = L.layers.get_all_layers(net.net)
            L.layers.set_all_param_values(_layers, startparams)
            if freeze:
                net.freeze_params(exclude=exclude)

        train_idxs = r[split, :3]
        val_idxs = r[split, 3:4]
        test_idxs = r[split, 4:]

        X, y, S = [np.concatenate(np.array(Z)[train_idxs]) for Z in [Xs, ys, Ss]]
        Xv, yv, Sv = [np.concatenate(np.array(Z)[val_idxs]) for Z in [Xs, ys, Ss]]
        Xt, yt, St = [np.concatenate(np.array(Z)[test_idxs]) for Z in [Xs, ys, Ss]]
        X, y = augment((X, y))
        S = np.concatenate([S, S, S, S])
        self.train(net, training_data=(X, y), validation_data=(Xv, yv))
        self.test(net, testing_data=(Xt, yt))
        time_elapsed = time.time() - starttime

        return net

def run_full_fit(arch, archname):
    """
    Runs the full fitting experiment,
    pretraining on later experiments and testing on first.

    Saves data as it goes to avoid eating memory.
    """

    # start training
    trainer = DefaultTrainer(stopthresh=75, print_interval=20)
    net_list = trainer.train_all(architecture=arch, data=data, seed=985227)

    # save params
    for i, n in enumerate(net_list):
        fname = '{} {} split agg fit exp 1-4'.format(archname, i)
        n.save_params(os.path.join(paramsdir, fname))

    tuner = FineTuner(stopthresh=20)
    for i, n in enumerate(net_list):
        for j in range(5):
            fname = '{} {} agg fit exp 1-4 {} tune fit exp 0'.format(archname, i, j)
            params = L.get_all_param_values(n.net)
            net = tuner.train_all(
                architecture=arch, data=hvhdata,
                split=j, startparams=params, freeze=True
            )
            net.save_params(os.path.join(paramsdir, fname))

    return None
<|endoftext|>


<commit_before>from june.app import app, prepare_app

app.config.from_pyfile('_config/development.py')
prepare_app()

from june.account import models
models.db.create_all()
<commit_msg>create node app tables<commit_after>from june.app import app, prepare_app

app.config.from_pyfile('_config/development.py')
prepare_app()

from june import account, node
account.models.db.create_all()
node.models.db.create_all()
<|endoftext|>


<commit_before>__all__ = ["hist2d", "error_ellipse", "corner"]

__version__ = "0.0.1"

import numpy as np
import scipy.special as sp

import matplotlib.pyplot as pl
from matplotlib.ticker import MaxNLocator
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.patches import Ellipse
import matplotlib.cm as cm

def error_ellipse(mu, cov, ax=None, **kwargs):
    """
    Plot the error ellipse at a point given it's covariance matrix.

    """
    # some sane defaults
    facecolor = kwargs.pop('facecolor', 'none')
    edgecolor = kwargs.pop('edgecolor', 'k')

    x, y = mu
    U, S, V = np.linalg.svd(cov)
    theta = np.degrees(np.arctan2(U[1, 0], U[0, 0]))
    ellipsePlot = Ellipse(xy=[x, y],
            width=2 * np.sqrt(S[0]),
            height=2 * np.sqrt(S[1]),
            angle=theta,
            facecolor=facecolor, edgecolor=edgecolor, **kwargs)

    if ax is None:
        ax = pl.gca()
    ax.add_patch(ellipsePlot)

def hist2d(x, y, *args, **kwargs):
    """
    Plot a 2-D histogram of samples.

    """
    ax = kwargs.pop("ax", pl.gca())

    extent = kwargs.pop("extent", [[x.min(), x.max()], [y.min(), y.max()]])
    bins = kwargs.pop("bins", 50)
    color = kwargs.pop("color", 'k')

    cmap = cm.get_cmap("gray")
    cmap._init()
    cmap._lut[:-3, :-1] = 0.
    cmap._lut[:-3, -1] = np.linspace(1, 0, cmap.N)

    X = np.linspace(extent[0][0], extent[0][1], bins + 1)
    Y = np.linspace(extent[1][0], extent[1][1], bins + 1)
    H, X, Y = np.histogram2d(x.flatten(), y.flatten(), bins=(X, Y))

    V = sp.erf(np.arange(0.5, 2.1, 0.5) / np.sqrt(2))
    Hflat = H.flatten()
    inds = np.argsort(Hflat)[::-1]
    Hflat = Hflat[inds]
    sm = np.cumsum(Hflat)
    sm /= sm[-1]

    for i, v0 in enumerate(V):
        try:
            V[i] = Hflat[sm <= v0][-1]
        except:
            V[i] = Hflat[0]

    X, Y = 0.5 * (X[1:] + X[:-1]), 0.5 * (Y[1:] + Y[:-1])

    ax.plot(x, y, "o", color=color, ms=1.5, zorder=-1, alpha=0.1,
            rasterized=True)
    ax.contourf(X, Y, H.T, [V[-1], 0.],
        cmap=LinearSegmentedColormap.from_list("cmap", ([1] * 3, [1] * 3),
            N=2))
    ax.pcolor(X, Y, H.max() - H.T, cmap=cmap)
    ax.contour(X, Y, H.T, V, colors=color)

    data = np.vstack([x, y])
    mu = np.mean(data, axis=1)
    cov = np.cov(data)
    error_ellipse(mu, cov, ax=ax, edgecolor="r", ls="dashed")

    ax.set_xlim(extent[0])
    ax.set_ylim(extent[1])

def corner(xs, labels=None, extents=None, truths=None, truth_color="#4682b4",
           **kwargs):
    K = len(xs)
    factor = 2.0           # size of one side of one panel
    lbdim = 0.5 * factor   # size of left/bottom margin
    trdim = 0.05 * factor  # size of top/right margin
    whspace = 0.05         # w/hspace size
    plotdim = factor * K + factor * (K - 1.) * whspace
    dim = lbdim + plotdim + trdim
    fig = pl.figure(figsize=(dim, dim))
    lb = lbdim / dim
    tr = (lbdim + plotdim) / dim
    fig.subplots_adjust(left=lb, bottom=lb, right=tr, top=tr,
                        wspace=whspace, hspace=whspace)

    if extents is None:
        extents = [[x.min(), x.max()] for x in xs]

    for i, x in enumerate(xs):
        # Plot the histograms.
        ax = fig.add_subplot(K, K, i * (K + 1) + 1)
        ax.hist(x, bins=kwargs.get("bins", 50), range=extents[i],
                histtype="step", color=kwargs.get("color", "k"))
        if truths is not None:
            ax.axvline(truths[i], color=truth_color)

        # Set up the axes.
        ax.set_xlim(extents[i])
        ax.set_yticklabels([])
        ax.xaxis.set_major_locator(MaxNLocator(5))

        # Not so DRY.
        if i < K - 1:
            ax.set_xticklabels([])
        else:
            [l.set_rotation(45) for l in ax.get_xticklabels()]
            if labels is not None:
                ax.set_xlabel(labels[i])
                ax.xaxis.set_label_coords(0.5, -0.3)

        for j, y in enumerate(xs[:i]):
            ax = fig.add_subplot(K, K, (i * K + j) + 1)
            hist2d(y, x, ax=ax, extent=[extents[j], extents[i]], **kwargs)

            if truths is not None:
                ax.plot(truths[j], truths[i], "s", color=truth_color)
                ax.axvline(truths[j], color=truth_color)
                ax.axhline(truths[i], color=truth_color)

            ax.xaxis.set_major_locator(MaxNLocator(5))
            ax.yaxis.set_major_locator(MaxNLocator(5))

            if i < K - 1:
                ax.set_xticklabels([])
            else:
                [l.set_rotation(45) for l in ax.get_xticklabels()]
                if labels is not None:
                    ax.set_xlabel(labels[j])
                    ax.xaxis.set_label_coords(0.5, -0.3)

            if j > 0:
                ax.set_yticklabels([])
            else:
                [l.set_rotation(45) for l in ax.get_yticklabels()]
                if labels is not None:
                    ax.set_ylabel(labels[i])
                    ax.yaxis.set_label_coords(-0.3, 0.5)

    return fig
<commit_msg>Corrected shift between pcolor and contours<commit_after>__all__ = ["hist2d", "error_ellipse", "corner"]

__version__ = "0.0.1"

import numpy as np
import scipy.special as sp

import matplotlib.pyplot as pl
from matplotlib.ticker import MaxNLocator
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.patches import Ellipse
import matplotlib.cm as cm

def error_ellipse(mu, cov, ax=None, **kwargs):
    """
    Plot the error ellipse at a point given it's covariance matrix.

    """
    # some sane defaults
    facecolor = kwargs.pop('facecolor', 'none')
    edgecolor = kwargs.pop('edgecolor', 'k')

    x, y = mu
    U, S, V = np.linalg.svd(cov)
    theta = np.degrees(np.arctan2(U[1, 0], U[0, 0]))
    ellipsePlot = Ellipse(xy=[x, y],
            width=2 * np.sqrt(S[0]),
            height=2 * np.sqrt(S[1]),
            angle=theta,
            facecolor=facecolor, edgecolor=edgecolor, **kwargs)

    if ax is None:
        ax = pl.gca()
    ax.add_patch(ellipsePlot)

def hist2d(x, y, *args, **kwargs):
    """
    Plot a 2-D histogram of samples.

    """
    ax = kwargs.pop("ax", pl.gca())

    extent = kwargs.pop("extent", [[x.min(), x.max()], [y.min(), y.max()]])
    bins = kwargs.pop("bins", 50)
    color = kwargs.pop("color", 'k')

    cmap = cm.get_cmap("gray")
    cmap._init()
    cmap._lut[:-3, :-1] = 0.
    cmap._lut[:-3, -1] = np.linspace(1, 0, cmap.N)

    X = np.linspace(extent[0][0], extent[0][1], bins + 1)
    Y = np.linspace(extent[1][0], extent[1][1], bins + 1)
    H, X, Y = np.histogram2d(x.flatten(), y.flatten(), bins=(X, Y))

    V = sp.erf(np.arange(1, 2.1, 0.5) / np.sqrt(2))
    Hflat = H.flatten()
    inds = np.argsort(Hflat)[::-1]
    Hflat = Hflat[inds]
    sm = np.cumsum(Hflat)
    sm /= sm[-1]

    for i, v0 in enumerate(V):
        try:
            V[i] = Hflat[sm <= v0][-1]
        except:
            V[i] = Hflat[0]

    X1, Y1 = 0.5 * (X[1:] + X[:-1]), 0.5 * (Y[1:] + Y[:-1])
    X, Y = X[:-1], Y[:-1]

    ax.plot(x, y, "o", color=color, ms=1.5, zorder=-1, alpha=0.1,
            rasterized=True)
    ax.contourf(X1, Y1, H.T, [V[-1], 0.],
        cmap=LinearSegmentedColormap.from_list("cmap", ([1] * 3, [1] * 3),
            N=2))
    ax.pcolor(X, Y, H.max() - H.T, cmap=cmap)
    ax.contour(X1, Y1, H.T, V, colors=color)

    data = np.vstack([x, y])
    mu = np.mean(data, axis=1)
    cov = np.cov(data)
    error_ellipse(mu, cov, ax=ax, edgecolor="r", ls="dashed")

    ax.set_xlim(extent[0])
    ax.set_ylim(extent[1])

def corner(xs, labels=None, extents=None, truths=None, truth_color="#4682b4",
           **kwargs):
    K = len(xs)
    factor = 2.0           # size of one side of one panel
    lbdim = 0.5 * factor   # size of left/bottom margin
    trdim = 0.05 * factor  # size of top/right margin
    whspace = 0.05         # w/hspace size
    plotdim = factor * K + factor * (K - 1.) * whspace
    dim = lbdim + plotdim + trdim
    fig = pl.figure(figsize=(dim, dim))
    lb = lbdim / dim
    tr = (lbdim + plotdim) / dim
    fig.subplots_adjust(left=lb, bottom=lb, right=tr, top=tr,
                        wspace=whspace, hspace=whspace)

    if extents is None:
        extents = [[x.min(), x.max()] for x in xs]

    for i, x in enumerate(xs):
        # Plot the histograms.
        ax = fig.add_subplot(K, K, i * (K + 1) + 1)
        ax.hist(x, bins=kwargs.get("bins", 50), range=extents[i],
                histtype="step", color=kwargs.get("color", "k"))
        if truths is not None:
            ax.axvline(truths[i], color=truth_color)

        # Set up the axes.
        ax.set_xlim(extents[i])
        ax.set_yticklabels([])
        ax.xaxis.set_major_locator(MaxNLocator(5))

        # Not so DRY.
        if i < K - 1:
            ax.set_xticklabels([])
        else:
            [l.set_rotation(45) for l in ax.get_xticklabels()]
            if labels is not None:
                ax.set_xlabel(labels[i])
                ax.xaxis.set_label_coords(0.5, -0.3)

        for j, y in enumerate(xs[:i]):
            ax = fig.add_subplot(K, K, (i * K + j) + 1)
            hist2d(y, x, ax=ax, extent=[extents[j], extents[i]], **kwargs)

            if truths is not None:
                ax.plot(truths[j], truths[i], "s", color=truth_color)
                ax.axvline(truths[j], color=truth_color)
                ax.axhline(truths[i], color=truth_color)

            ax.xaxis.set_major_locator(MaxNLocator(5))
            ax.yaxis.set_major_locator(MaxNLocator(5))

            if i < K - 1:
                ax.set_xticklabels([])
            else:
                [l.set_rotation(45) for l in ax.get_xticklabels()]
                if labels is not None:
                    ax.set_xlabel(labels[j])
                    ax.xaxis.set_label_coords(0.5, -0.3)

            if j > 0:
                ax.set_yticklabels([])
            else:
                [l.set_rotation(45) for l in ax.get_yticklabels()]
                if labels is not None:
                    ax.set_ylabel(labels[i])
                    ax.yaxis.set_label_coords(-0.3, 0.5)

    return fig
<|endoftext|>


<commit_before>#!/usr/bin/python
#
# Copyright (c) 2010-2012 Joshua Hughes <kivhift@gmail.com>
#
import os
import tempfile

import PyQt4
from PyQt4.uic import compileUi

pyqt4_path = PyQt4.__path__[0]
def _tool_path(t):
    return os.path.join(pyqt4_path, t)

lrelease_tool = _tool_path('lrelease')
pylupdate4_tool = _tool_path('pylupdate4')
pyrcc4_tool = _tool_path('pyrcc4')

def pyui_name(ui):
    '''
    Generate the python-module name from the Qt UI file.
    '''
    h, t = os.path.split(ui)
    return os.path.join(h, 'ui_' + t.replace('.ui', '.py'))

def pyqrc_name(qrc):
    '''
    Generate the python-module name from the Qt QRC file.
    '''
    h, t = os.path.split(qrc)
    t = t.replace('.qrc', '.py')
    t = t.replace('-', '_')
    return os.path.join(h, 'qrc_' + t)

def generate_pyui(target, source, env):
    '''
    Generate a Python module for the given Qt UI file.
    '''
    with open(str(target[0]), 'wb') as f:
        compileUi(str(source[0]), f, execute = True, indent = 4)

def setup_pyqt4_builders(env, builder_factory):
    env['BUILDERS']['PyUic4'] = builder_factory(action = generate_pyui)
    env['BUILDERS']['PyRcc4'] = builder_factory(
        action = pyrcc4_tool + ' -py2 -o $TARGET $SOURCE')
    env['BUILDERS']['PyLupdate4'] = builder_factory(
        action = pylupdate4_tool + ' -noobsolete -verbose $SOURCES -ts $TARGET')
    env['BUILDERS']['Lrelease'] = builder_factory(action = lrelease_tool
        + ' -compress -nounfinished -removeidentical $SOURCES -qm $TARGET')

def pyuic4(env, ui):
    '''
    Carefully generate the Python module for the given Qt UI file.
    '''
    t = env.Precious(env.NoClean(env.PyUic4(
        target = pyui_name(ui), source = ui)))
    env.Depends(t, ui)

    return t

def pyrcc4(env, qrc, depends = []):
    '''
    Carefully generate the resource module from the given QRC file with the
    given dependencies.
    '''
    t = env.Precious(env.NoClean(env.PyRcc4(
        target = pyqrc_name(qrc), source = qrc)))
    env.Depends(t, depends)

    return t

def pylupdate4(env, ts, src):
    '''
    Carefully update the translation file ts from the given source files.
    '''
    t = env.Precious(env.NoClean(env.PyLupdate4(target = ts, source = src)))
    env.Depends(t, src)

    return t

def lrelease(env, qm, ts):
    '''
    Carefully generate the "compiled" translation file qm from the given ts
    file(s).
    '''
    t = env.Precious(env.NoClean(env.Lrelease(target = qm, source = ts)))
    env.Depends(t, ts)

    return t
<commit_msg>pyqt4: Allow translations that are same as source.<commit_after>#!/usr/bin/python
#
# Copyright (c) 2010-2012 Joshua Hughes <kivhift@gmail.com>
#
import os
import tempfile

import PyQt4
from PyQt4.uic import compileUi

pyqt4_path = PyQt4.__path__[0]
def _tool_path(t):
    return os.path.join(pyqt4_path, t)

lrelease_tool = _tool_path('lrelease')
pylupdate4_tool = _tool_path('pylupdate4')
pyrcc4_tool = _tool_path('pyrcc4')

def pyui_name(ui):
    '''
    Generate the python-module name from the Qt UI file.
    '''
    h, t = os.path.split(ui)
    return os.path.join(h, 'ui_' + t.replace('.ui', '.py'))

def pyqrc_name(qrc):
    '''
    Generate the python-module name from the Qt QRC file.
    '''
    h, t = os.path.split(qrc)
    t = t.replace('.qrc', '.py')
    t = t.replace('-', '_')
    return os.path.join(h, 'qrc_' + t)

def generate_pyui(target, source, env):
    '''
    Generate a Python module for the given Qt UI file.
    '''
    with open(str(target[0]), 'wb') as f:
        compileUi(str(source[0]), f, execute = True, indent = 4)

def setup_pyqt4_builders(env, builder_factory):
    env['BUILDERS']['PyUic4'] = builder_factory(action = generate_pyui)
    env['BUILDERS']['PyRcc4'] = builder_factory(
        action = pyrcc4_tool + ' -py2 -o $TARGET $SOURCE')
    env['BUILDERS']['PyLupdate4'] = builder_factory(
        action = pylupdate4_tool + ' -noobsolete -verbose $SOURCES -ts $TARGET')
    env['BUILDERS']['Lrelease'] = builder_factory(action = lrelease_tool
        + ' -compress -nounfinished $SOURCES -qm $TARGET')

def pyuic4(env, ui):
    '''
    Carefully generate the Python module for the given Qt UI file.
    '''
    t = env.Precious(env.NoClean(env.PyUic4(
        target = pyui_name(ui), source = ui)))
    env.Depends(t, ui)

    return t

def pyrcc4(env, qrc, depends = []):
    '''
    Carefully generate the resource module from the given QRC file with the
    given dependencies.
    '''
    t = env.Precious(env.NoClean(env.PyRcc4(
        target = pyqrc_name(qrc), source = qrc)))
    env.Depends(t, depends)

    return t

def pylupdate4(env, ts, src):
    '''
    Carefully update the translation file ts from the given source files.
    '''
    t = env.Precious(env.NoClean(env.PyLupdate4(target = ts, source = src)))
    env.Depends(t, src)

    return t

def lrelease(env, qm, ts):
    '''
    Carefully generate the "compiled" translation file qm from the given ts
    file(s).
    '''
    t = env.Precious(env.NoClean(env.Lrelease(target = qm, source = ts)))
    env.Depends(t, ts)

    return t
<|endoftext|>


<commit_before>import re
import matlab2cpp as mc
import armadillo as arma

def add_indenting(text):
    """Add identing to text
    """

    lines = text.split("\n")

    indent = 0
    for i in xrange(len(lines)):
        line = lines[i]

        # Fix indentation and linesplit
        if line in ("}", "} ;") or line[:4] == "} //":
            indent -= 1
            line = "  "*indent + line

        elif line == "{":
            line = "  "*indent + line
            indent += 1
        else:
            line = "  "*indent + line
        lines[i] = line

    text = "\n".join(lines)

    return text

def number_fix(text):
    """Code has allot of '-1' statements in indexing. This code substitutes
explicit number subtractions with the single index equivalent.

Examples:
    >>> print number_fix("a(8-1, 5-1)")
    a(7, 4)
    """
    # Cosmetic fix
    for p0,p1,p2 in set(re.findall(r"(([ ,(\[])(-?\d+)-1)", text)):
        val = int(p2)-1
        val = p1+str(val)
        text = val.join(text.split(p0))

    for p0,p1,p2 in \
            set(re.findall(r"(([+\- ])(\d+)-1)", text)):
        if p1=="-":     val = int(p2)+1
        else:           val = int(p2)-1
        if val:         val = p1+str(val)
        else:           val = ""
        text = val.join(text.split(p0))

    text = re.sub(r"\+-", r"-", text)
    return text

def strip(text):
    """Remove trailing spaces and linefeeds.
    """
    if not text: return text

    start = 0
    while text[start] in "\n ":
        start += 1
    end = 0
    while text[end-1] in "\n ":
        end -= 1

    if end:
        text = text[start:end]
    else:
        text = text[start:]

    return text

def Project(node):
    return ""

def Program(node):
    arma.include(node)
    return ""

def Includes(node):
    return "", "\n", ""

def Headers(node):
    return "", "\n", ""

def Header(node):
    func = node.program[1][node.program[1].names.index(node.name)]
    if func.backend == "func_return":
        code = func[1][0].type + " " + func.name + "(" +\
            ", ".join([p.type + " " + p.name for p in func[2]]) + ") ;"

    elif func.backend == "func_returns" and not func[1]:
        code = "void " + func.name + "(" +\
            ", ".join([p.type + " " + p.name for p in func[2]]) + ") ;"

    elif func.backend == "func_returns" and func[1]:
        code = "void " + func.name + "(" +\
            ", ".join([p.type + " " + p.name for p in func[2]]) + ", " +\
            ", ".join([p.type + "& " + p.name for p in func[1]]) + ") ;"
    return code

Include = "%(name)s"

def Funcs(node):
    text = "\n\n".join(map(str, node[:]))
    # text = add_indenting(text)
    # text = number_fix(text)
    text = re.sub(r"\n *(\n *)+", r"\n\n", text)
    # text = strip(text)

    return text

def Inlines(node):

    if not node:
        return ""

    text = "\n\n".join([n.name for n in node])

    text = """#ifndef MCONVERT_H
#define MCONVERT_H

namespace m2cpp
{
""" + text + """
}

#endif
"""
    # text = add_indenting(text)
    return text

def Inline(node):
    return ""

Structs = "", "\n\n", ""

def Log(node):
    return "", "\n\n", ""

def Error(node):
    cls = node.name.split(":")[0]
    return 'Error in class ' + cls + ''' on line %(line)d:
%(code)s
''' + " "*node.cur + "^\n%(value)s"

def Warning(node):
    cls = node.name.split(":")[0]
    return 'Warning in class ' + cls + ''' on line %(line)d:
%(code)s
''' + " "*node.cur + "^\n%(value)s"

def Struct(node):

    name = "_"+node.name.capitalize()
    out = "struct " + name + "\n{"

    declares = {}
    for child in node[:]:

        type = child.type
        if type == "func_lambda":
            type == "std::function"

        if type == "structs":
            continue

        if type not in declares:
            declares[type] = []

        declares[type].append(child)

    for key, val in declares.items():
        out = out + "\n" + key + " " + ", ".join([str(v) for v in val]) + " ;"
    out = out + "\n} ;"

    # out = add_indenting(out)

    return out

if __name__ == "__main__":
    import doctest
    doctest.testmod()
<commit_msg>Modified the regular expression in number_fix in _program.py a = 1-1/2 was "fixed" to a = 0/2. Now it is "unfixed" -> a = 1-1/2<commit_after>import re
import matlab2cpp as mc
import armadillo as arma

def add_indenting(text):
    """Add identing to text
    """

    lines = text.split("\n")

    indent = 0
    for i in xrange(len(lines)):
        line = lines[i]

        # Fix indentation and linesplit
        if line in ("}", "} ;") or line[:4] == "} //":
            indent -= 1
            line = "  "*indent + line

        elif line == "{":
            line = "  "*indent + line
            indent += 1
        else:
            line = "  "*indent + line
        lines[i] = line

    text = "\n".join(lines)

    return text

def number_fix(text):
    """Code has allot of '-1' statements in indexing. This code substitutes
explicit number subtractions with the single index equivalent.

Examples:
    >>> print number_fix("a(8-1, 5-1)")
    a(7, 4)
    """
    # Cosmetic fix
    for p0,p1,p2 in set(re.findall(r"(([ ,(\[])(-?\d+)-1(?![*/]))", text)):
        val = int(p2)-1
        val = p1+str(val)
        text = val.join(text.split(p0))

    for p0,p1,p2 in \
            set(re.findall(r"(([+\- ])(\d+)-1(?![*/]))", text)):
        if p1=="-":     val = int(p2)+1
        else:           val = int(p2)-1
        if val:         val = p1+str(val)
        else:           val = ""
        text = val.join(text.split(p0))

    text = re.sub(r"\+-", r"-", text)
    return text

def strip(text):
    """Remove trailing spaces and linefeeds.
    """
    if not text: return text

    start = 0
    while text[start] in "\n ":
        start += 1
    end = 0
    while text[end-1] in "\n ":
        end -= 1

    if end:
        text = text[start:end]
    else:
        text = text[start:]

    return text

def Project(node):
    return ""

def Program(node):
    arma.include(node)
    return ""

def Includes(node):
    return "", "\n", ""

def Headers(node):
    return "", "\n", ""

def Header(node):
    func = node.program[1][node.program[1].names.index(node.name)]
    if func.backend == "func_return":
        code = func[1][0].type + " " + func.name + "(" +\
            ", ".join([p.type + " " + p.name for p in func[2]]) + ") ;"

    elif func.backend == "func_returns" and not func[1]:
        code = "void " + func.name + "(" +\
            ", ".join([p.type + " " + p.name for p in func[2]]) + ") ;"

    elif func.backend == "func_returns" and func[1]:
        code = "void " + func.name + "(" +\
            ", ".join([p.type + " " + p.name for p in func[2]]) + ", " +\
            ", ".join([p.type + "& " + p.name for p in func[1]]) + ") ;"
    return code

Include = "%(name)s"

def Funcs(node):
    text = "\n\n".join(map(str, node[:]))
    # text = add_indenting(text)
    # text = number_fix(text)
    text = re.sub(r"\n *(\n *)+", r"\n\n", text)
    # text = strip(text)

    return text

def Inlines(node):

    if not node:
        return ""

    text = "\n\n".join([n.name for n in node])

    text = """#ifndef MCONVERT_H
#define MCONVERT_H

namespace m2cpp
{
""" + text + """
}

#endif
"""
    # text = add_indenting(text)
    return text

def Inline(node):
    return ""

Structs = "", "\n\n", ""

def Log(node):
    return "", "\n\n", ""

def Error(node):
    cls = node.name.split(":")[0]
    return 'Error in class ' + cls + ''' on line %(line)d:
%(code)s
''' + " "*node.cur + "^\n%(value)s"

def Warning(node):
    cls = node.name.split(":")[0]
    return 'Warning in class ' + cls + ''' on line %(line)d:
%(code)s
''' + " "*node.cur + "^\n%(value)s"

def Struct(node):

    name = "_"+node.name.capitalize()
    out = "struct " + name + "\n{"

    declares = {}
    for child in node[:]:

        type = child.type
        if type == "func_lambda":
            type == "std::function"

        if type == "structs":
            continue

        if type not in declares:
            declares[type] = []

        declares[type].append(child)

    for key, val in declares.items():
        out = out + "\n" + key + " " + ", ".join([str(v) for v in val]) + " ;"
    out = out + "\n} ;"

    # out = add_indenting(out)

    return out

if __name__ == "__main__":
    import doctest
    doctest.testmod()
<|endoftext|>


<commit_before>import json
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.contrib.auth.decorators import login_required
from django.views.decorators.cache import cache_page
from django.db.models import Q
from django.core import serializers
from django.core.exceptions import ObjectDoesNotExist
from .forms import BotBufferForm
from models import Challenge, Bot, UserProfile
from game.tasks import validate_bot

def index(request, match_id=None):
    return render(request, 'home.html', {'tab': 'arena', 'match_id': match_id})

def about(request):
    return render(request, 'about.html', {'tab': 'about'})

@login_required
def scoreboard(request):
    #bots = Bot.objects.all().order_by('-points')
    users = UserProfile.objects.filter(current_bot__isnull=False).order_by('-score')
    users = ((user, request.user.profile.latest_match_id(user)) for user in users)
    challenges = Challenge.objects.filter(requested_by=request.user.profile, challenger_bot=request.user.profile.current_bot, played=False, canceled=False)
#    if challenges.count() > 0:
#        pending_challenges = True
#    else:
#        pending_challenges = False

    pending_challenged_bots = [c.challenged_bot for c in challenges]

    played_challenges = Challenge.objects.filter(requested_by=request.user.profile, played=True, canceled=False)
    challenged_bots = [c.challenged_bot for c in played_challenges]

    return render(request, 'scoreboard.html', {'tab': 'score',
                'users': users,
                'challenged_bots': challenged_bots,
                'pending_challenged_bots': pending_challenged_bots})

@login_required
def tournament(request):
    users = UserProfile.objects.filter(current_bot__isnull=False).order_by('-score')

    return render(request, 'tournament.html', {'tab': 'tournament', 'users': users})

@login_required
def mybots(request):
    user_prof = UserProfile.objects.get(user=request.user)
    if request.method == 'POST':
        form = BotBufferForm(request.POST)
        if not form.is_valid():
            print "ERROR in form!"
            return
        new_code = form.cleaned_data['code']
        user_prof.code = new_code

        if 'publish_buffer' in request.POST:
            bot = Bot()
            bot.owner = user_prof
            bot.code = new_code
            bot.save()
            validate_bot.delay(bot.id, new_code)
            user_prof.current_bot = bot

        user_prof.save()
        return redirect('/mybots')
    else:
        form = BotBufferForm(instance=user_prof)

    return render(request, "my_bots.html", {
        'form': form,
        'user_prof': user_prof,
        'tab': 'mybots',
        'my_bots': reversed(Bot.objects.filter(owner=user_prof))
    })

@login_required
@csrf_exempt
@require_POST
def challenge(request):
    if request.is_ajax():
        challenge_bot_id = json.loads(request.body)['msg']
        challenge_bot = Bot.objects.get(pk=challenge_bot_id)

        # get the user current bot
        user_prof = UserProfile.objects.get(user=request.user)
        if not user_prof.current_bot:
            print "Can not challenge if does not have a bot!"
            return HttpResponse("Error")
        if challenge_bot.owner == user_prof:
            print "[CHEATING!] - wrong challenge bot!"
            return HttpResponse("Error")

        # challenged bot must be the owners current bot
        if not challenge_bot.is_current_bot:
            print "[CHEATING!] - wrong challenge bot!, must be the owners current bot!."
            return HttpResponse("Error")

        print "Got a challenge for bot: ", challenge_bot

        # Get pending challenges for this user
        challenges = Challenge.objects.filter(requested_by=user_prof, played=False, canceled=False)
        if challenges.count() > 0:
            # has pending challenges, must wait.
            return HttpResponse("Can not challenge more than one bot at a time")

        # Check if these bots haven't already played.
        #played_challs = Challenge.objects.filter(challenger_bot=user_prof.current_bot,
        #    challenged_bot=challenge_bot, played=True)

        #if played_challs.count() > 0:
        #    # has already played against this bot, must upload a new one
        #    return HttpResponse("Already played against this bot!. Upload a new one.")
        if (user_prof.current_bot.valid != Bot.READY
                or challenge_bot.valid != Bot.READY):
            return JsonResponse({'success': False, 'msg': 'One of the bot is not READY' })

        new_challengue = Challenge()
        new_challengue.requested_by = user_prof
        new_challengue.challenger_bot = user_prof.current_bot
        new_challengue.challenged_bot = challenge_bot
        new_challengue.save()

        return JsonResponse({'success': True})

@login_required
@cache_page(60)
def main_match(request):
    return HttpResponse(None)

@login_required
def my_matches(request):
    matches = Challenge.objects.filter(Q(challenger_bot__owner=request.user) | Q(challenged_bot__owner=request.user) & Q(canceled=False)).order_by('-creation_date').select_related('challenger_bot__owner__user', 'challenged_bot__owner__user', 'winner_bot__owner__user')
    return render(request, 'mymatches.html', {'matches': matches, 'tab': 'my-matches'})

@login_required
def get_match(request, match_id):
    try:
        challenge = Challenge.objects.get(pk=match_id)
        return JsonResponse({'success': True, 'data': json.loads(challenge.result)})
    except ObjectDoesNotExist:
        return JsonResponse({'success': False})

@login_required
def get_bot_status(request, bot_id):
    try:
        bot = Bot.objects.get(pk=bot_id)
        return JsonResponse({'success': True, 'status': bot.valid, 'code': bot.code ,'reason': bot.invalid_reason})
    except ObjectDoesNotExist:
        return JsonResponse({'success': False})

@login_required
def random_test_match(request):
    return HttpResponse(None)

@login_required
def bot_code(request, bot_pk):
    if bot_pk == "0":
        user_prof = UserProfile.objects.get(user=request.user)
        return HttpResponse(user_prof.my_buffer)

    bot_code = Bot.objects.get(pk=bot_pk, owner=request.user).code
    return HttpResponse(bot_code)

@login_required
def get_playlist(request):
    challenges = Challenge.objects.filter(played=True, canceled=False).order_by('-creation_date')
    if not challenges:
        return JsonResponse({'success': False, 'data': []})
    challs = [ [ch.id, str(ch)] for ch in challenges ]

    return JsonResponse({'success': True, 'data': challs})
<commit_msg>filtered get_match view<commit_after>import json
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.contrib.auth.decorators import login_required
from django.views.decorators.cache import cache_page
from django.db.models import Q
from django.core import serializers
from django.core.exceptions import ObjectDoesNotExist
from .forms import BotBufferForm
from models import Challenge, Bot, UserProfile
from game.tasks import validate_bot

def index(request, match_id=None):
    return render(request, 'home.html', {'tab': 'arena', 'match_id': match_id})

def about(request):
    return render(request, 'about.html', {'tab': 'about'})

@login_required
def scoreboard(request):
    #bots = Bot.objects.all().order_by('-points')
    users = UserProfile.objects.filter(current_bot__isnull=False).order_by('-score')
    users = ((user, request.user.profile.latest_match_id(user)) for user in users)
    challenges = Challenge.objects.filter(requested_by=request.user.profile, challenger_bot=request.user.profile.current_bot, played=False, canceled=False)
#    if challenges.count() > 0:
#        pending_challenges = True
#    else:
#        pending_challenges = False

    pending_challenged_bots = [c.challenged_bot for c in challenges]

    played_challenges = Challenge.objects.filter(requested_by=request.user.profile, played=True, canceled=False)
    challenged_bots = [c.challenged_bot for c in played_challenges]

    return render(request, 'scoreboard.html', {'tab': 'score',
                'users': users,
                'challenged_bots': challenged_bots,
                'pending_challenged_bots': pending_challenged_bots})

@login_required
def tournament(request):
    users = UserProfile.objects.filter(current_bot__isnull=False).order_by('-score')

    return render(request, 'tournament.html', {'tab': 'tournament', 'users': users})

@login_required
def mybots(request):
    user_prof = UserProfile.objects.get(user=request.user)
    if request.method == 'POST':
        form = BotBufferForm(request.POST)
        if not form.is_valid():
            print "ERROR in form!"
            return
        new_code = form.cleaned_data['code']
        user_prof.code = new_code

        if 'publish_buffer' in request.POST:
            bot = Bot()
            bot.owner = user_prof
            bot.code = new_code
            bot.save()
            validate_bot.delay(bot.id, new_code)
            user_prof.current_bot = bot

        user_prof.save()
        return redirect('/mybots')
    else:
        form = BotBufferForm(instance=user_prof)

    return render(request, "my_bots.html", {
        'form': form,
        'user_prof': user_prof,
        'tab': 'mybots',
        'my_bots': reversed(Bot.objects.filter(owner=user_prof))
    })

@login_required
@csrf_exempt
@require_POST
def challenge(request):
    if request.is_ajax():
        challenge_bot_id = json.loads(request.body)['msg']
        challenge_bot = Bot.objects.get(pk=challenge_bot_id)

        # get the user current bot
        user_prof = UserProfile.objects.get(user=request.user)
        if not user_prof.current_bot:
            print "Can not challenge if does not have a bot!"
            return HttpResponse("Error")
        if challenge_bot.owner == user_prof:
            print "[CHEATING!] - wrong challenge bot!"
            return HttpResponse("Error")

        # challenged bot must be the owners current bot
        if not challenge_bot.is_current_bot:
            print "[CHEATING!] - wrong challenge bot!, must be the owners current bot!."
            return HttpResponse("Error")

        print "Got a challenge for bot: ", challenge_bot

        # Get pending challenges for this user
        challenges = Challenge.objects.filter(requested_by=user_prof, played=False, canceled=False)
        if challenges.count() > 0:
            # has pending challenges, must wait.
            return HttpResponse("Can not challenge more than one bot at a time")

        # Check if these bots haven't already played.
        #played_challs = Challenge.objects.filter(challenger_bot=user_prof.current_bot,
        #    challenged_bot=challenge_bot, played=True)

        #if played_challs.count() > 0:
        #    # has already played against this bot, must upload a new one
        #    return HttpResponse("Already played against this bot!. Upload a new one.")
        if (user_prof.current_bot.valid != Bot.READY
                or challenge_bot.valid != Bot.READY):
            return JsonResponse({'success': False, 'msg': 'One of the bot is not READY' })

        new_challengue = Challenge()
        new_challengue.requested_by = user_prof
        new_challengue.challenger_bot = user_prof.current_bot
        new_challengue.challenged_bot = challenge_bot
        new_challengue.save()

        return JsonResponse({'success': True})

@login_required
@cache_page(60)
def main_match(request):
    return HttpResponse(None)

@login_required
def my_matches(request):
    matches = Challenge.objects.filter(Q(challenger_bot__owner=request.user) | Q(challenged_bot__owner=request.user) & Q(canceled=False)).order_by('-creation_date').select_related('challenger_bot__owner__user', 'challenged_bot__owner__user', 'winner_bot__owner__user')
    return render(request, 'mymatches.html', {'matches': matches, 'tab': 'my-matches'})

@login_required
def get_match(request, match_id):
    try:
        challenge = Challenge.objects.get(pk=match_id)
        if challenge.canceled:
            return JsonResponse({'success': False})
        else:
            return JsonResponse({'success': True, 'data': json.loads(challenge.result)})
    except ObjectDoesNotExist:
        return JsonResponse({'success': False})

@login_required
def get_bot_status(request, bot_id):
    try:
        bot = Bot.objects.get(pk=bot_id)
        return JsonResponse({'success': True, 'status': bot.valid, 'code': bot.code ,'reason': bot.invalid_reason})
    except ObjectDoesNotExist:
        return JsonResponse({'success': False})

@login_required
def random_test_match(request):
    return HttpResponse(None)

@login_required
def bot_code(request, bot_pk):
    if bot_pk == "0":
        user_prof = UserProfile.objects.get(user=request.user)
        return HttpResponse(user_prof.my_buffer)

    bot_code = Bot.objects.get(pk=bot_pk, owner=request.user).code
    return HttpResponse(bot_code)

@login_required
def get_playlist(request):
    challenges = Challenge.objects.filter(played=True, canceled=False).order_by('-creation_date')
    if not challenges:
        return JsonResponse({'success': False, 'data': []})
    challs = [ [ch.id, str(ch)] for ch in challenges ]

    return JsonResponse({'success': True, 'data': challs})
<|endoftext|>


<commit_before>from tpg.action_object import ActionObject
from tpg.program import Program
from tpg.learner import Learner
from tpg.team import Team
from tpg.agent import Agent
import random
import numpy as np
import pickle
from tpg.configuration import configurer

"""
Functionality for actually growing TPG and evolving it to be functional.
"""
class Trainer:

    """
    Create a trainer to store the various evolutionary parameters, and runs under
    them.

    Important parameters:

    actions: List of actions, typically just set as 'range(n)' (n=18 for Atari).

    teamPopSize: Initial number of teams / root teams, to be maintained through
    evolution.

    rootBasedPop: Whether population size is based on root teams. If true there
    are always roughly the same amount of root teams (uses more RAM).
    Else it ensures the total team population size is 'teamPopSize' (uses
    less RAM).
    """
    def __init__(self, actions, teamPopSize=360, rootBasedPop=True, gap=0.5,
        inputSize=30720, nRegisters=8, initMaxTeamSize=5, initMaxProgSize=128,
        pLrnDel=0.7, pLrnAdd=0.7, pLrnMut=0.3, pProgMut=0.66, pActMut=0.33,
        pActAtom=0.5, pInstDel=0.5, pInstAdd=0.5, pInstSwp=1.0, pInstMut=1.0,
        doElites=True, memType=None, memMatrixShape=(100,8), rampancy=(-1,0,1),
        operationSet="def"):

        # store all necessary params

        # first store actions properly
        doReal = self.setUpActions(actions)

        # population params
        self.teamPopSize = teamPopSize
        # whether population size is based on root teams or all teams
        self.rootBasedPop = rootBasedPop
        self.gap = gap # portion of root teams to remove each generation

        # input to agent (must be at-least size of input/state from environment)
        self.inputSize = inputSize # defaulted to number of Atari screen pixels
        # number of local memory registers each learner will have
        self.nRegisters = nRegisters

        # params for initializing evolution
        self.initMaxTeamSize = initMaxTeamSize # size of team = # of learners
        self.initMaxProgSize = initMaxProgSize # size of program = # of instructions

        # params for continued evolution
        self.pLrnDel = pLrnDel
        self.pLrnAdd = pLrnAdd
        self.pLrnMut = pLrnMut
        self.pProgMut = pProgMut
        self.pActMut = pActMut
        self.pActAtom = pActAtom
        self.pInstDel = pInstDel
        self.pInstAdd = pInstAdd
        self.pInstSwp = pInstSwp
        self.pInstMut = pInstMut

        # whether to keep elites
        self.doElites = doElites

        self.memType = memType
        self.memMatrixShape = memMatrixShape

        # fix range of rampancy if invalid
        if rampancy[2] <= rampancy[1]:
            rampancy[2] = rampancy[1]+1
        self.rampancy = rampancy

        self.operationSet = operationSet

        # core components of TPG
        self.teams = []
        self.rootTeams = []
        self.learners = []
        self.elites = [] # save best at each task

        self.generation = 0 # track this

        # configure tpg functions and variable appropriately now
        configurer.configure(self, Trainer, Agent, Team, Learner, ActionObject, Program,
            memType is not None, memType, doReal, operationSet)

        from tpg.configuration.extra_params import MutateParams, ActVars

        self.mutateParams = MutateParams(*self.mutateParamVals)
        self.actVars = ActVars(*self.actVarVals)

        self.initializePopulations()

    """
    Sets up the actions properly, splitting action codes, and if needed, action
    lengths. Returns whether doing real actions.
    """
    def setUpActions(self, actions):
        if isinstance(actions, int):
            # all discrete actions
            self.actionCodes = range(actions)
            doReal = False
        else: # list of lengths of each action
            # some may be real actions
            self.actionCodes = range(len(actions))
            self.actionLengths = list(actions)
            doReal = True

        return doReal

    """
    Initializes a popoulation of teams and learners generated randomly with only
    atomic actions.
    """
    def initializePopulations(self):
        for i in range(self.teamPopSize):
            # create 2 unique actions and learners
            a1,a2 = random.sample(range(len(self.actionCodes)), 2)

            l1 = Learner(program=Program(maxProgramLength=self.initMaxProgSize,
                                         nOperations=self.nOperations,
                                         nDestinations=self.nRegisters,
                                         inputSize=self.inputSize,
                                         initParams=self.mutateParams),
                        actionObj=ActionObject(actionIndex=a1, initParams=self.mutateParams),
                        numRegisters=self.nRegisters,
                        initParams=self.mutateParams)
            l2 = Learner(program=Program(maxProgramLength=self.initMaxProgSize,
                                         nOperations=self.nOperations,
                                         nDestinations=self.nRegisters,
                                         inputSize=self.inputSize,
                                         initParams=self.mutateParams),
                        actionObj=ActionObject(actionIndex=a2, initParams=self.mutateParams),
                        numRegisters=self.nRegisters,
                        initParams=self.mutateParams)

            # save learner population
            self.learners.append(l1)
            self.learners.append(l2)

            # create team and add initial learners
            team = Team()
            team.addLearner(l1)
            team.addLearner(l2)

            # add more learners
            moreLearners = random.randint(0, self.initMaxTeamSize-2)
            for i in range(moreLearners):
                # select action
                act = random.choice(range(len(self.actionCodes)))

                # create new learner
                learner = Learner(program=Program(maxProgramLength=self.initMaxProgSize,
                                             nOperations=self.nOperations,
                                             nDestinations=self.nRegisters,
                                             inputSize=self.inputSize,
                                             initParams=self.mutateParams),
                            actionObj=ActionObject(actionIndex=act, initParams=self.mutateParams),
                            numRegisters=self.nRegisters,
                            initParams=self.mutateParams)

                team.addLearner(learner)
                self.learners.append(learner)

            # save to team populations
            self.teams.append(team)
            self.rootTeams.append(team)

    """
    Gets rootTeams/agents. Sorts decending by sortTasks, and skips individuals
    who don't have scores for all skipTasks.
    """
    def getAgents(self, sortTasks=[], multiTaskType='min', skipTasks=[]):
        # remove those that get skipped
        rTeams = [team for team in self.rootTeams
                if len(skipTasks) == 0
                        or any(task not in team.outcomes for task in skipTasks)]

        if len(sortTasks) == 0: # just get all
            return [Agent(team, num=i, actVars=self.actVars)
                    for i,team in enumerate(rTeams)]
        else:
            # apply scores/fitness to root teams
            self.scoreIndividuals(sortTasks, multiTaskType=multiTaskType, doElites=False)
            # return teams sorted by fitness
            return [Agent(team, num=i, actVars=self.actVars)
                    for i,team in enumerate(sorted(rTeams,
                                    key=lambda tm: tm.fitness, reverse=True))]

    """
    Apply saved scores from list to the agents.
    """
    def applyScores(self, scores): # used when multiprocessing
        for score in scores:
            for rt in self.rootTeams:
                if score[0] == rt.id:
                    for task, outcome in score[1].items():
                        rt.outcomes[task] = outcome
                    break # on to next score

        return self.rootTeams

    """
    Evolve the populations for improvements.
    """
    def evolve(self, tasks=['task'], multiTaskType='min'):
        self.scoreIndividuals(tasks, multiTaskType=multiTaskType,
                doElites=self.doElites) # assign scores to individuals
        self.saveFitnessStats() # save fitness stats
        self.select() # select individuals to keep
        self.generate() # create new individuals from those kept
        self.nextEpoch() # set up for next generation

    """
    Assigns a fitness to each agent based on performance at the tasks. Assigns
    fitness values, or just returns sorted root teams.
    """
    def scoreIndividuals(self, tasks, multiTaskType='min', doElites=True):
        # handle generation of new elites, typically just done in evolution
        if doElites:
            # get the best agent at each task
            self.elites = [] # clear old elites
            for task in tasks:
                self.elites.append(max([team for team in self.rootTeams],
                                        key=lambda t: t.outcomes[task]))

        if len(tasks) == 1: # single fitness
            for team in self.rootTeams:
                team.fitness = team.outcomes[tasks[0]]
        else: # multi fitness
            # assign fitness to each agent based on tasks and score type
            if 'pareto' not in multiTaskType or 'lexicase' not in multiTaskType:
                self.simpleScorer(tasks, multiTaskType=multiTaskType)
            elif multiTaskType == 'paretoDominate':
                self.paretoDominateScorer(tasks)
            elif multiTaskType == 'paretoNonDominated':
                self.paretoNonDominatedScorer(tasks)
            elif multiTaskType == 'lexicaseStatic':
                self.lexicaseStaticScorer(tasks)
            elif multiTaskType == 'lexicaseDynamic':
                self.lexicaseDynamicScorer(tasks)

    """
    Gets either the min, max, or average score from each individual for ranking.
    """
    def simpleScorer(self, tasks, multiTaskType='min'):
        # first find min and max in each task
        mins = []
        maxs = []
        for task in tasks:
            mins.append(min([team.outcomes[task] for team in self.rootTeams]))
            maxs.append(max([team.outcomes[task] for team in self.rootTeams]))

        # assign fitness
        if multiTaskType == 'min':
            for rt in self.rootTeams:
                rt.fitness = min([(rt.outcomes[task]-mins[i])/(maxs[i]-mins[i])
                        for i,task in enumerate(tasks)])
        elif multiTaskType == 'max':
            for rt in self.rootTeams:
                rt.fitness = max([(rt.outcomes[task]-mins[i])/(maxs[i]-mins[i])
                        for i,task in enumerate(tasks)])
        elif multiTaskType == 'average':
            for rt in self.rootTeams:
                scores = [(rt.outcomes[task]-mins[i])/(maxs[i]-mins[i])
                            for i,task in enumerate(tasks)]
                rt.fitness = sum(scores)/len(scores)

    """
    Rank agents based on how many other agents it dominates
    """
    def paretoDominateScorer(self, tasks):
        for t1 in self.rootTeams:
            t1.fitness = 0
            for t2 in self.rootTeams:
                if t1 == t2:
                    continue # don't compare to self

                # compare on all tasks
                if all([t1.outcomes[task] >= t2.outcomes[task]
                         for task in tasks]):
                    t1.fitness += 1

    """
    Rank agents based on how many other agents don't dominate it
    """
    def paretoNonDominatedScorer(self, tasks):
        for t1 in self.rootTeams:
            t1.fitness = 0
            for t2 in self.rootTeams:
                if t1 == t2:
                    continue # don't compare to self

                # compare on all tasks
                if all([t1.outcomes[task] < t2.outcomes[task]
                         for task in tasks]):
                    t1.fitness -= 1

    def lexicaseStaticScorer(self, tasks):
        stasks = list(tasks)
        random.shuffle(stasks)

        for rt in self.rootTeams:
            rt.fitness = rt.outcomes[tasks[0]]

    def lexicaseDynamicScorer(self, tasks):
        pass

    """
    Save some stats on the fitness.
    """
    def saveFitnessStats(self):
        fitnesses = []
        for rt in self.rootTeams:
            fitnesses.append(rt.fitness)

        self.fitnessStats = {}
        self.fitnessStats['fitnesses'] = fitnesses
        self.fitnessStats['min'] = min(fitnesses)
        self.fitnessStats['max'] = max(fitnesses)
        self.fitnessStats['average'] = sum(fitnesses)/len(fitnesses)

    """
    Gets stats on some task.
    """
    def getTaskStats(self, task):
        scores = []
        for rt in self.rootTeams:
            scores.append(rt.outcomes[task])

        scoreStats = {}
        scoreStats['scores'] = scores
        scoreStats['min'] = min(scores)
        scoreStats['max'] = max(scores)
        scoreStats['average'] = sum(scores)/len(scores)

        return scoreStats

    """
    Delete a portion of the population according to gap size.
    """
    def select(self):
        rankedTeams = sorted(self.rootTeams, key=lambda rt: rt.fitness, reverse=True)
        numKeep = len(self.rootTeams) - int(len(self.rootTeams)*self.gap)
        deleteTeams = rankedTeams[numKeep:]

        # delete the team unless it is an elite (best at some task at-least)
        # don't delete elites because they may not be root
        for team in [t for t in deleteTeams if t not in self.elites]:
            for learner in team.learners:
                # delete learner from population if this is last team referencing
                if learner.numTeamsReferencing == 1:
                    # remove reference to team if applicable
                    if not learner.isActionAtomic():
                        learner.getActionTeam().numLearnersReferencing -= 1

                    self.learners.remove(learner) # permanently remove

            # remove learners from team and delete team from populations
            team.removeLearners()
            self.teams.remove(team)
            self.rootTeams.remove(team)

    """
    Generates new rootTeams based on existing teams.
    """
    def generate(self):

        oLearners = list(self.learners)
        oTeams = list(self.teams)

        # update generation in mutateParams
        self.mutateParams = self.mutateParams._replace(generation=self.generation)

        while (len(self.teams) < self.teamPopSize or
                (self.rootBasedPop and self.countRootTeams() < self.teamPopSize)):

            # get parent root team, and child to be based on that
            parent = random.choice(self.rootTeams)
            child = Team()

            # child starts just like parent
            for learner in parent.learners:
                child.addLearner(learner)

            # then mutates
            child.mutate(self.mutateParams, oLearners, oTeams)

            self.teams.append(child)
            self.rootTeams.append(child)

    """
    Finalize populations and prepare for next generation/epoch.
    """
    def nextEpoch(self):
        # add in newly added learners, and decide root teams
        self.rootTeams = []
        for team in self.teams:
            # add any new learners to the population
            for learner in team.learners:
                if learner not in self.learners:
                    self.learners.append(learner)

            # maybe make root team
            if team.numLearnersReferencing == 0 or team in self.elites:
                self.rootTeams.append(team)

        self.generation += 1

    """
    Get the number of root teams currently residing in the teams population.
    """
    def countRootTeams(self):
        numRTeams = 0
        for team in self.teams:
            if team.numLearnersReferencing == 0:
                numRTeams += 1

        return numRTeams

    """
    Save the trainer to the file, saving any class values to the instance.
    """
    def saveToFile(self, fileName):
        self.teamIdCount = Team.idCount
        self.learnerIdCount = Learner.idCount
        self.programIdCount = Program.idCount

        pickle.dump(self, open(fileName, 'wb'))

"""
Load some trainer from the file, returning it and repopulate class values.
"""
def loadTrainer(fileName):
    trainer = pickle.load(open(fileName, 'rb'))

    Team.idCount = trainer.teamIdCount
    Learner.idCount = trainer.learnerIdCount
    Program.idCount = trainer.programIdCount

    return trainer
<commit_msg>update rampancy fixing<commit_after>from tpg.action_object import ActionObject
from tpg.program import Program
from tpg.learner import Learner
from tpg.team import Team
from tpg.agent import Agent
import random
import numpy as np
import pickle
from tpg.configuration import configurer

"""
Functionality for actually growing TPG and evolving it to be functional.
"""
class Trainer:

    """
    Create a trainer to store the various evolutionary parameters, and runs under
    them.

    Important parameters:

    actions: List of actions, typically just set as 'range(n)' (n=18 for Atari).

    teamPopSize: Initial number of teams / root teams, to be maintained through
    evolution.

    rootBasedPop: Whether population size is based on root teams. If true there
    are always roughly the same amount of root teams (uses more RAM).
    Else it ensures the total team population size is 'teamPopSize' (uses
    less RAM).
    """
    def __init__(self, actions, teamPopSize=360, rootBasedPop=True, gap=0.5,
        inputSize=30720, nRegisters=8, initMaxTeamSize=5, initMaxProgSize=128,
        pLrnDel=0.7, pLrnAdd=0.7, pLrnMut=0.3, pProgMut=0.66, pActMut=0.33,
        pActAtom=0.5, pInstDel=0.5, pInstAdd=0.5, pInstSwp=1.0, pInstMut=1.0,
        doElites=True, memType=None, memMatrixShape=(100,8), rampancy=(-1,0,1),
        operationSet="def"):

        # store all necessary params

        # first store actions properly
        doReal = self.setUpActions(actions)

        # population params
        self.teamPopSize = teamPopSize
        # whether population size is based on root teams or all teams
        self.rootBasedPop = rootBasedPop
        self.gap = gap # portion of root teams to remove each generation

        # input to agent (must be at-least size of input/state from environment)
        self.inputSize = inputSize # defaulted to number of Atari screen pixels
        # number of local memory registers each learner will have
        self.nRegisters = nRegisters

        # params for initializing evolution
        self.initMaxTeamSize = initMaxTeamSize # size of team = # of learners
        self.initMaxProgSize = initMaxProgSize # size of program = # of instructions

        # params for continued evolution
        self.pLrnDel = pLrnDel
        self.pLrnAdd = pLrnAdd
        self.pLrnMut = pLrnMut
        self.pProgMut = pProgMut
        self.pActMut = pActMut
        self.pActAtom = pActAtom
        self.pInstDel = pInstDel
        self.pInstAdd = pInstAdd
        self.pInstSwp = pInstSwp
        self.pInstMut = pInstMut

        # whether to keep elites
        self.doElites = doElites

        self.memType = memType
        self.memMatrixShape = memMatrixShape

        # fix range of rampancy if invalid
        if rampancy[2] <= rampancy[1]:
            rampancy = (rampancy[0], rampancy[1], rampancy[1]+1)
        self.rampancy = rampancy

        self.operationSet = operationSet

        # core components of TPG
        self.teams = []
        self.rootTeams = []
        self.learners = []
        self.elites = [] # save best at each task

        self.generation = 0 # track this

        # configure tpg functions and variable appropriately now
        configurer.configure(self, Trainer, Agent, Team, Learner, ActionObject, Program,
            memType is not None, memType, doReal, operationSet)

        from tpg.configuration.extra_params import MutateParams, ActVars

        self.mutateParams = MutateParams(*self.mutateParamVals)
        self.actVars = ActVars(*self.actVarVals)

        self.initializePopulations()

    """
    Sets up the actions properly, splitting action codes, and if needed, action
    lengths. Returns whether doing real actions.
    """
    def setUpActions(self, actions):
        if isinstance(actions, int):
            # all discrete actions
            self.actionCodes = range(actions)
            doReal = False
        else: # list of lengths of each action
            # some may be real actions
            self.actionCodes = range(len(actions))
            self.actionLengths = list(actions)
            doReal = True

        return doReal

    """
    Initializes a popoulation of teams and learners generated randomly with only
    atomic actions.
    """
    def initializePopulations(self):
        for i in range(self.teamPopSize):
            # create 2 unique actions and learners
            a1,a2 = random.sample(range(len(self.actionCodes)), 2)

            l1 = Learner(program=Program(maxProgramLength=self.initMaxProgSize,
                                         nOperations=self.nOperations,
                                         nDestinations=self.nRegisters,
                                         inputSize=self.inputSize,
                                         initParams=self.mutateParams),
                        actionObj=ActionObject(actionIndex=a1, initParams=self.mutateParams),
                        numRegisters=self.nRegisters,
                        initParams=self.mutateParams)
            l2 = Learner(program=Program(maxProgramLength=self.initMaxProgSize,
                                         nOperations=self.nOperations,
                                         nDestinations=self.nRegisters,
                                         inputSize=self.inputSize,
                                         initParams=self.mutateParams),
                        actionObj=ActionObject(actionIndex=a2, initParams=self.mutateParams),
                        numRegisters=self.nRegisters,
                        initParams=self.mutateParams)

            # save learner population
            self.learners.append(l1)
            self.learners.append(l2)

            # create team and add initial learners
            team = Team()
            team.addLearner(l1)
            team.addLearner(l2)

            # add more learners
            moreLearners = random.randint(0, self.initMaxTeamSize-2)
            for i in range(moreLearners):
                # select action
                act = random.choice(range(len(self.actionCodes)))

                # create new learner
                learner = Learner(program=Program(maxProgramLength=self.initMaxProgSize,
                                             nOperations=self.nOperations,
                                             nDestinations=self.nRegisters,
                                             inputSize=self.inputSize,
                                             initParams=self.mutateParams),
                            actionObj=ActionObject(actionIndex=act, initParams=self.mutateParams),
                            numRegisters=self.nRegisters,
                            initParams=self.mutateParams)

                team.addLearner(learner)
                self.learners.append(learner)

            # save to team populations
            self.teams.append(team)
            self.rootTeams.append(team)

    """
    Gets rootTeams/agents. Sorts decending by sortTasks, and skips individuals
    who don't have scores for all skipTasks.
    """
    def getAgents(self, sortTasks=[], multiTaskType='min', skipTasks=[]):
        # remove those that get skipped
        rTeams = [team for team in self.rootTeams
                if len(skipTasks) == 0
                        or any(task not in team.outcomes for task in skipTasks)]

        if len(sortTasks) == 0: # just get all
            return [Agent(team, num=i, actVars=self.actVars)
                    for i,team in enumerate(rTeams)]
        else:
            # apply scores/fitness to root teams
            self.scoreIndividuals(sortTasks, multiTaskType=multiTaskType, doElites=False)
            # return teams sorted by fitness
            return [Agent(team, num=i, actVars=self.actVars)
                    for i,team in enumerate(sorted(rTeams,
                                    key=lambda tm: tm.fitness, reverse=True))]

    """
    Apply saved scores from list to the agents.
    """
    def applyScores(self, scores): # used when multiprocessing
        for score in scores:
            for rt in self.rootTeams:
                if score[0] == rt.id:
                    for task, outcome in score[1].items():
                        rt.outcomes[task] = outcome
                    break # on to next score

        return self.rootTeams

    """
    Evolve the populations for improvements.
    """
    def evolve(self, tasks=['task'], multiTaskType='min'):
        self.scoreIndividuals(tasks, multiTaskType=multiTaskType,
                doElites=self.doElites) # assign scores to individuals
        self.saveFitnessStats() # save fitness stats
        self.select() # select individuals to keep
        self.generate() # create new individuals from those kept
        self.nextEpoch() # set up for next generation

    """
    Assigns a fitness to each agent based on performance at the tasks. Assigns
    fitness values, or just returns sorted root teams.
    """
    def scoreIndividuals(self, tasks, multiTaskType='min', doElites=True):
        # handle generation of new elites, typically just done in evolution
        if doElites:
            # get the best agent at each task
            self.elites = [] # clear old elites
            for task in tasks:
                self.elites.append(max([team for team in self.rootTeams],
                                        key=lambda t: t.outcomes[task]))

        if len(tasks) == 1: # single fitness
            for team in self.rootTeams:
                team.fitness = team.outcomes[tasks[0]]
        else: # multi fitness
            # assign fitness to each agent based on tasks and score type
            if 'pareto' not in multiTaskType or 'lexicase' not in multiTaskType:
                self.simpleScorer(tasks, multiTaskType=multiTaskType)
            elif multiTaskType == 'paretoDominate':
                self.paretoDominateScorer(tasks)
            elif multiTaskType == 'paretoNonDominated':
                self.paretoNonDominatedScorer(tasks)
            elif multiTaskType == 'lexicaseStatic':
                self.lexicaseStaticScorer(tasks)
            elif multiTaskType == 'lexicaseDynamic':
                self.lexicaseDynamicScorer(tasks)

    """
    Gets either the min, max, or average score from each individual for ranking.
    """
    def simpleScorer(self, tasks, multiTaskType='min'):
        # first find min and max in each task
        mins = []
        maxs = []
        for task in tasks:
            mins.append(min([team.outcomes[task] for team in self.rootTeams]))
            maxs.append(max([team.outcomes[task] for team in self.rootTeams]))

        # assign fitness
        if multiTaskType == 'min':
            for rt in self.rootTeams:
                rt.fitness = min([(rt.outcomes[task]-mins[i])/(maxs[i]-mins[i])
                        for i,task in enumerate(tasks)])
        elif multiTaskType == 'max':
            for rt in self.rootTeams:
                rt.fitness = max([(rt.outcomes[task]-mins[i])/(maxs[i]-mins[i])
                        for i,task in enumerate(tasks)])
        elif multiTaskType == 'average':
            for rt in self.rootTeams:
                scores = [(rt.outcomes[task]-mins[i])/(maxs[i]-mins[i])
                            for i,task in enumerate(tasks)]
                rt.fitness = sum(scores)/len(scores)

    """
    Rank agents based on how many other agents it dominates
    """
    def paretoDominateScorer(self, tasks):
        for t1 in self.rootTeams:
            t1.fitness = 0
            for t2 in self.rootTeams:
                if t1 == t2:
                    continue # don't compare to self

                # compare on all tasks
                if all([t1.outcomes[task] >= t2.outcomes[task]
                         for task in tasks]):
                    t1.fitness += 1

    """
    Rank agents based on how many other agents don't dominate it
    """
    def paretoNonDominatedScorer(self, tasks):
        for t1 in self.rootTeams:
            t1.fitness = 0
            for t2 in self.rootTeams:
                if t1 == t2:
                    continue # don't compare to self

                # compare on all tasks
                if all([t1.outcomes[task] < t2.outcomes[task]
                         for task in tasks]):
                    t1.fitness -= 1

    def lexicaseStaticScorer(self, tasks):
        stasks = list(tasks)
        random.shuffle(stasks)

        for rt in self.rootTeams:
            rt.fitness = rt.outcomes[tasks[0]]

    def lexicaseDynamicScorer(self, tasks):
        pass

    """
    Save some stats on the fitness.
    """
    def saveFitnessStats(self):
        fitnesses = []
        for rt in self.rootTeams:
            fitnesses.append(rt.fitness)

        self.fitnessStats = {}
        self.fitnessStats['fitnesses'] = fitnesses
        self.fitnessStats['min'] = min(fitnesses)
        self.fitnessStats['max'] = max(fitnesses)
        self.fitnessStats['average'] = sum(fitnesses)/len(fitnesses)

    """
    Gets stats on some task.
    """
    def getTaskStats(self, task):
        scores = []
        for rt in self.rootTeams:
            scores.append(rt.outcomes[task])

        scoreStats = {}
        scoreStats['scores'] = scores
        scoreStats['min'] = min(scores)
        scoreStats['max'] = max(scores)
        scoreStats['average'] = sum(scores)/len(scores)

        return scoreStats

    """
    Delete a portion of the population according to gap size.
    """
    def select(self):
        rankedTeams = sorted(self.rootTeams, key=lambda rt: rt.fitness, reverse=True)
        numKeep = len(self.rootTeams) - int(len(self.rootTeams)*self.gap)
        deleteTeams = rankedTeams[numKeep:]

        # delete the team unless it is an elite (best at some task at-least)
        # don't delete elites because they may not be root
        for team in [t for t in deleteTeams if t not in self.elites]:
            for learner in team.learners:
                # delete learner from population if this is last team referencing
                if learner.numTeamsReferencing == 1:
                    # remove reference to team if applicable
                    if not learner.isActionAtomic():
                        learner.getActionTeam().numLearnersReferencing -= 1

                    self.learners.remove(learner) # permanently remove

            # remove learners from team and delete team from populations
            team.removeLearners()
            self.teams.remove(team)
            self.rootTeams.remove(team)

    """
    Generates new rootTeams based on existing teams.
    """
    def generate(self):

        oLearners = list(self.learners)
        oTeams = list(self.teams)

        # update generation in mutateParams
        self.mutateParams = self.mutateParams._replace(generation=self.generation)

        while (len(self.teams) < self.teamPopSize or
                (self.rootBasedPop and self.countRootTeams() < self.teamPopSize)):

            # get parent root team, and child to be based on that
            parent = random.choice(self.rootTeams)
            child = Team()

            # child starts just like parent
            for learner in parent.learners:
                child.addLearner(learner)

            # then mutates
            child.mutate(self.mutateParams, oLearners, oTeams)

            self.teams.append(child)
            self.rootTeams.append(child)

    """
    Finalize populations and prepare for next generation/epoch.
    """
    def nextEpoch(self):
        # add in newly added learners, and decide root teams
        self.rootTeams = []
        for team in self.teams:
            # add any new learners to the population
            for learner in team.learners:
                if learner not in self.learners:
                    self.learners.append(learner)

            # maybe make root team
            if team.numLearnersReferencing == 0 or team in self.elites:
                self.rootTeams.append(team)

        self.generation += 1

    """
    Get the number of root teams currently residing in the teams population.
    """
    def countRootTeams(self):
        numRTeams = 0
        for team in self.teams:
            if team.numLearnersReferencing == 0:
                numRTeams += 1

        return numRTeams

    """
    Save the trainer to the file, saving any class values to the instance.
    """
    def saveToFile(self, fileName):
        self.teamIdCount = Team.idCount
        self.learnerIdCount = Learner.idCount
        self.programIdCount = Program.idCount

        pickle.dump(self, open(fileName, 'wb'))

"""
Load some trainer from the file, returning it and repopulate class values.
"""
def loadTrainer(fileName):
    trainer = pickle.load(open(fileName, 'rb'))

    Team.idCount = trainer.teamIdCount
    Learner.idCount = trainer.learnerIdCount
    Program.idCount = trainer.programIdCount

    return trainer
<|endoftext|>