
import numpy as np


def _index_to_indicator(matrix, maxIndex):
    shape = matrix.shape
    tensor = np.zeros((shape[0], maxIndex, shape[1]), dtype='float32')
    (obs, time) = np.mgrid[0:shape[0], 0:shape[1]]
    tensor[obs, matrix, time] = 1
    return tensor

def quadrant_classify(items, T=5):
    X = np.random.uniform(low=-1, high=1, size=(items, 2, T)).astype('float32')

    t = np.zeros((items, 5), dtype='int32')
    t += np.all([X[:, 0, :] < 0 , X[:, 1, :] >= 0], axis=0) * 1
    t += np.all([X[:, 0, :] < 0 , X[:, 1, :] < 0] , axis=0) * 2
    t += np.all([X[:, 0, :] >= 0, X[:, 1, :] < 0] , axis=0) * 3
    return (X, t)

def quadrant_cumsum_classify(items, T=5):
    X = np.random.uniform(low=-1, high=1, size=(items, 2, T)).astype('float32')
    Xsum = np.cumsum(X, axis=2)

    t = np.zeros((items, T), dtype='int32')
    t += np.all([Xsum[:, 0, :] < 0 , Xsum[:, 1, :] >= 0], axis=0) * 1
    t += np.all([Xsum[:, 0, :] < 0 , Xsum[:, 1, :] < 0] , axis=0) * 2
    t += np.all([Xsum[:, 0, :] >= 0, Xsum[:, 1, :] < 0] , axis=0) * 3
    return (X, t)

def quadrant_cumsum_decoder_sequence(items, T=15):
    X = np.random.uniform(low=-1, high=1, size=(items, T)).astype('float32')
    Xsum = np.cumsum(X, axis=1)

    t = np.zeros((items, T), dtype='int32')
    t += np.all([+0.0 <= Xsum, Xsum < +0.5], axis=0) * 1
    t += np.all([-0.5 <= Xsum, Xsum < +0.0], axis=0) * 2
    t += np.all([-1.0 <= Xsum, Xsum < -0.5], axis=0) * 3

    # Let the first quadrant be the <EOS> symbol
    for i in range(0, items):
        eos_index = T
        search = np.where(np.asarray(t[i, :]) == 0)[0]
        if (search.size > 0): eos_index = search[0]
        t[i, eos_index:]  = 0

    # Force end for the last time step
    t[:, -1] = 0

    return (X, t)

def mode_encoder_sequence(items, Tmin=17, Tmax=20):
    maxIndex = 10

    t = np.random.randint(1, maxIndex, size=(items, )).astype('int32')
    X = np.tile(t[:, np.newaxis], (1, Tmax))

    # Substitute random elements
    randsprseq = int(0.4 * Tmax)
    X[
        np.arange(0, items).repeat(randsprseq),
        np.random.randint(0, Tmax, size=(items * randsprseq))
    ] = np.random.randint(1, maxIndex, size=(items * randsprseq))

    # Stop the X sequence
    for i in range(0, items):
        stop = np.random.randint(Tmin, Tmax)
        X[i, stop:] = 0

    return (_index_to_indicator(X, 10), t)

def count_decoder_sequence(items, T=8, classes=5):
    # Create initial value
    X = np.random.uniform(0, classes, size=(items, 1))

    # Create targe by incrementing
    inc = np.tile(np.arange(0, T), (items, 1))
    t = np.mod(X + inc, classes)
    t = np.floor(t)

    # add <EOS>
    t = t + 1
    t = np.hstack([t, np.zeros((items, 1))])

    return ((X / classes).astype('float32'), t.astype('int32'))

def count_network_sequence(items, T=8, classes=5):
    # Create initial value
    X = np.random.uniform(0, classes, size=(items, 2, 1))
    X[:, 1, 0] = 0

    # Create targe by incrementing
    inc = np.tile(np.arange(0, T), (items, 1))
    t = np.mod(X[:, 0, 0][:, None] + inc, classes)
    t = np.floor(t)

    # add <EOS>
    t = t + 1
    t = np.hstack([t, np.zeros((items, 1))])

    return ((X / classes).astype('float32'), t.astype('int32'))

def subset_vocal_sequence(items, Tmin=17, Tmax=20):
    """
    This will generate a random input and target sequence of letters.

    All letters are used for the input sequence, the taget sequence is
    then the subset of the input where only vocals appear.
    """
    max_letter = 10  # 26 for full alphabet
    vocals = [1, 5, 9, 15, 21, 25]

    # The input sequence length is random between 2 and Tmax
    sequence_length = np.ones(items) * Tmin
    if (Tmin < Tmax):
        sequence_length = np.random.randint(Tmin, Tmax, size=items)

    # Generate a random sequence of letters
    letters = np.random.randint(1, max_letter + 1, size=(items, Tmax)).astype('int32')
    for index, length in enumerate(sequence_length):
        letters[index, length:] = 0

    # Generate a subset of the letter sequences containing only vocals
    vocal_mask = sum([letters == vocal for vocal in vocals])
    vocals = np.zeros((items, Tmax), dtype='int32')
    for index in range(0, items):
        vocal_scan = letters[index, vocal_mask[index, :].nonzero()].ravel()
        vocals[index, 0:vocal_scan.size] = vocal_scan

    return (
        _index_to_indicator(letters, max_letter + 1),
        vocals
    )

@@ -2900,17 +2900,17 @@
 ems, 2, 
-1
+2
 ))%0A    X
@@ -2917,12 +2917,50 @@
 %5B:, 
-1, 0
+0, 0%5D = 0%0A    X%5B:, 0, 1%5D = 1%0A    X%5B:, 1, 1
 %5D = 
@@ -3060,25 +3060,25 @@
 np.mod(X%5B:, 
-0
+1
 , 0%5D%5B:, None
@@ -3196,37 +3196,82 @@
 %5D)%0A%0A    
-return ((X / classes)
+# Normalize X%0A    X%5B:, 1, 0%5D = X%5B:, 1, 0%5D / classes%0A%0A    return (X
 .astype(

fix missing <EOS> in network count problem