import numpy as np


__all__ = ('add_bias_column', 'iter_until_converge', 'shuffle')


def add_bias_column(data):
    """ Transform input data to matrix and add as first column which
    contains all ones.

    Parameters
    ----------
    data : array-like
        Main matrix.

    Returns
    -------
    array-like
        Copied matrix with the new column at first position which contains
        all ones.
    """
    data = np.asmatrix(data)
    bias_vector = np.ones((data.shape[0], 1))
    return np.concatenate((bias_vector, np.asarray(data)), axis=1)


def iter_until_converge(network, epsilon, max_epochs):
    # Trigger first iteration and store first error term
    yield network.epoch
    network.epoch += 1
    error = network.last_error()

    while error > epsilon:
        yield network.epoch
        network.epoch += 1
        error = abs(network.last_error() - error)

        if network.epoch >= max_epochs:
            network.logs.log(
                "TRAIN",
                "Epoch #{} stopped. Network didn't converge "
                "after {} iterations".format(network.epoch, max_epochs)
            )
            break
    else:
        network.logs.log("TRAIN", "Epoch #{} stopped. Network converged."
                                  "".format(network.epoch))


def shuffle(*arrays):
    if not arrays:
        return tuple()

    first = arrays[0]
    n_samples = first.shape[0]

    for array in arrays:
        if n_samples != array.shape[0]:
            raise ValueError("All matrices muts have the same number of rows")

    indices = np.arange(n_samples)
    np.random.shuffle(indices)

    arrays = list(arrays)
    for i, array in enumerate(arrays):
        arrays[i] = array[indices]

    return arrays

@@ -694,39 +694,16 @@
 k.epoch%0A
-    network.epoch += 1%0A
     erro
@@ -727,16 +727,16 @@
 error()%0A
+
 %0A    whi
@@ -755,16 +755,43 @@
 psilon:%0A
+        network.epoch += 1%0A
         
@@ -814,35 +814,8 @@
 och%0A
-        network.epoch += 1%0A
     
@@ -899,16 +899,36 @@
 x_epochs
+ and error %3C epsilon
 :%0A      
@@ -1124,16 +1124,16 @@
       )%0A
-
         
@@ -1141,16 +1141,206 @@
    break
+%0A%0A    if np.isnan(error) or np.isinf(error):%0A        network.logs.log(%22TRAIN%22, %22Epoch #%7B%7D stopped. Network error value is %22%0A                                  %22invalid%22.format(network.epoch))
 %0A    els

Fix converge training procedure for undefined error values. Fix problem with epoch incrementor.