# Multi-headed multivariate MLP
from numpy import array, hstack
from keras.models import Model
from keras.layers import Input, Dense
from keras.layers.merge import concatenate

# Split a multivariate time series into samples
def split_sequences(sequences, n_steps):
    X, y = list(), list()
    for i in range(len(sequences)):
        # Find the end of this pattern
        end_ix = i + n_steps
        # Check if we are beyond the dataset
        if end_ix > len(sequences) - 1:
            break
        # Gather input and output parts of the pattern
        seq_x, seq_y = sequences[i: end_ix, :-1], sequences[end_ix, -1]
        X.append(seq_x)
        y.append(seq_y)
    return array(X), array(y)

# Define input sequences
in_seq1 = array([10, 20, 30, 40, 50, 60, 70, 80, 90])
in_seq2 = array([15, 25, 35, 45, 55, 65, 75, 85, 95])
out_seq = array([in_seq1[i] + in_seq2[i] for i in range(len(in_seq1))])

# Reshape the data to [rows, columns]
in_seq1 = in_seq1.reshape((len(in_seq1), 1))
in_seq2 = in_seq2.reshape((len(in_seq2), 1))
out_seq = out_seq.reshape((len(out_seq), 1))
# Stack the columns horizontally
dataset = hstack((in_seq1, in_seq2, out_seq))

# Choose the number of time steps
n_steps = 3

# Convert into input/output
X, y = split_sequences(dataset, n_steps)

# Separate input data
X1 = X[:, :, 0]
X2 = X[:, :, 1]

# First input model
visible1 = Input(shape = (n_steps, ))
dense1 = Dense(100, activation = 'relu')(visible1)

# Second input model
visible2 = Input(shape = (n_steps, ))
dense2 = Dense(100, activation = 'relu')(visible2)

# Merge input models
merge = concatenate([dense1, dense2])
output = Dense(1)(merge)

# Connect input and output models
model = Model(inputs = [visible1, visible2], outputs = output)
model.compile(optimizer = 'adam', loss = 'mse')

# Fit the model
model.fit([X1, X2], y, epochs = 2000, verbose = 0)

# Make predictions
x_input = array([[70, 75], [80, 85], [90, 95]])
x1 = x_input[:, 0].reshape((1, n_steps))
x2 = x_input[:, 1].reshape((1, n_steps))
y_hat = model.predict([x1, x2], verbose = 0)
print(y_hat)
