text:
# coding: utf-8
# Copyright (C) 2016 UKP lab
#
# Author: Daniil Sorokin (ukp.tu-darmstadt.de/ukp-home/)
#
import itertools
import numpy as np
np.random.seed(1)

from keras import layers, models
from keras import backend as K
from keras import regularizers

from utils import embedding_utils
from utils import graph

import tqdm

from semanticgraph import graph_utils

RESOURCES_FOLDER = "../resources/"
property_blacklist = embedding_utils.load_blacklist(RESOURCES_FOLDER + "property_blacklist.txt")

def model_RnnMarkers(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)
    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    word_embeddings = layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                         input_length=max_sent_len, weights=[embeddings],
                         mask_zero=True, trainable=False)(sentence_input)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.Embedding(output_dim=p['position_emb'], input_dim=4, input_length=max_sent_len,
                         mask_zero=True, W_regularizer = regularizers.l2(), trainable=True)(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = getattr(layers, p['rnn1'])(p['units1'], return_sequences=True, consume_less='gpu' if p['gpu'] else "cpu")(x)
    sentence_vector = getattr(layers, p['rnn1'])(p['units1'], consume_less='gpu' if p['gpu'] else "cpu")(x)

    # # If specified apply a set of fully-connected layers
    # for i in range(p["penultimate_layers"]):
    #     sentence_vector = layers.Dense(p['units2'], activation="tanh")(sentence_vector)

    # Apply softmax
    sentence_vector = layers.Dropout(p['dropout1'])(sentence_vector)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(sentence_vector)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_CNN(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)
    # Take sentence encoded as indices split in three parts and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    word_embeddings = layers.Embedding(output_dim=embeddings.shape[1],
                                       input_dim=embeddings.shape[0],
                                       input_length=max_sent_len, weights=[embeddings],
                                       mask_zero=True, trainable=False)(sentence_input)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(2, max_sent_len,), dtype='int8', name='entity_markers')

    pos_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=p['position_emb'], input_dim=(max_sent_len*2)+1, input_length=max_sent_len,
                                                                      mask_zero=False, W_regularizer = regularizers.l2(), trainable=True),  name='pos_embedding')(entity_markers)

    pos_embeddings = layers.Permute((2,1,3))(pos_embeddings)
    pos_embeddings = layers.Reshape((max_sent_len, p['position_emb']*2))(pos_embeddings)

    # Merge word and position embeddings and apply the specified amount of CNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")

    x = MaskedConvolution1D(nb_filter=p['units1'], filter_length=p['window_size'], border_mode='same')(x)
    sentence_vector = MaskedGlobalMaxPooling1D()(x)

    sentence_vector = layers.Lambda(lambda l: K.tanh(l))(sentence_vector)

    # Apply softmax
    sentence_vector = layers.Dropout(p['dropout1'])(sentence_vector)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(sentence_vector)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_PCNN(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)
    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    word_embeddings = layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                       input_length=max_sent_len, weights=[embeddings],
                                       mask_zero=True, trainable=False)(sentence_input)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.Embedding(output_dim=p['position_emb'], input_dim=4, input_length=max_sent_len,
                                      mask_zero=True, W_regularizer = regularizers.l2(), trainable=True)(entity_markers)

    # Merge word and position embeddings and apply the specified amount of CNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")

    for i in range(p["rnn1_layers"]-1):
        x = getattr(layers, p['rnn1'])(p['units1'], return_sequences=True, consume_less='gpu' if p['gpu'] else "cpu")(x)
    sentence_vector = getattr(layers, p['rnn1'])(p['units1'], consume_less='gpu' if p['gpu'] else "cpu")(x)

    # If specified apply a set of fully-connected layers
    for i in range(p["penultimate_layers"]):
        sentence_vector = layers.Dense(p['units2'], activation="tanh")(sentence_vector)

    # Apply softmax
    sentence_vector = layers.Dropout(p['dropout1'])(sentence_vector)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(sentence_vector)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersAttention(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    word_embeddings = layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                         input_length=max_sent_len, weights=[embeddings],
                         mask_zero=True, trainable=False)(sentence_input)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.Embedding(output_dim=p['position_emb'], input_dim=4, input_length=max_sent_len,
                         mask_zero=True, W_regularizer = regularizers.l2(),  trainable=True)(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = getattr(layers, p['rnn1'])(p['units1'], return_sequences=True, consume_less='gpu' if p['gpu'] else "cpu")(x)
    sentence_vector = getattr(layers, p['rnn1'])(p['units1'], return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu")(x)

    ### Attention ###
    # Compute memory vectors for each word and then compute score by multiplying each with the sentence vector
    word_memories = layers.wrappers.TimeDistributed(layers.Dense(p['units1'], activation="relu"),
                                                    name = "word_memories")(word_embeddings)
    word_scores = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,2)),
                     output_shape=(max_sent_len,), name = "scores")([sentence_vector, word_memories])
    word_scores = layers.Activation('softmax')(word_scores)
    # Compute context vectors for each word and take a sum of them weighted by the computed scores
    context_vectors = layers.wrappers.TimeDistributed(layers.Dense(p['units1'], activation="relu"),
                                                      name = "context_vectors")(word_embeddings)
    memory_output = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,1)),
                     output_shape=(p['units1'],), name = "memory_output")([context_vectors, word_scores])

    # Merge the sentence vector and the memory output
    x = layers.merge([memory_output, sentence_vector], mode=p['memory_merge'])

    # Apply softmax
    x = layers.Dropout(p['dropout1'])(x)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(x)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersAttentionV2(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    word_embeddings = layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                               input_length=max_sent_len, weights=[embeddings],
                               mask_zero=True, trainable=False)(sentence_input)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.Embedding(output_dim=p['position_emb'], input_dim=4, input_length=max_sent_len,
                         mask_zero=True, W_regularizer = regularizers.l2(),  trainable=True)(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = getattr(layers, p['rnn1'])(p['units1'], return_sequences=True, consume_less='gpu' if p['gpu'] else "cpu")(x)
    sentence_matrix = getattr(layers, p['rnn1'])(p['units1'], return_sequences=True, consume_less='gpu' if p['gpu'] else "cpu")(x)
    # Store all output vectors of the RNN and the final one as the sentence vector
    sentence_vector = GetOutput()(x)

    ### Attention ###
    # Compute memory vectors for each word and then compute score by multiplying each with the sentence vector
    word_memories = layers.wrappers.TimeDistributed(layers.Dense(p['units1'], activation="relu"),
                                                    name = "word_memories")(word_embeddings)
    word_scores = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,2)),
                     output_shape=(max_sent_len,), name = "word_scores")([sentence_vector, word_memories])
    word_scores = layers.Activation('softmax')(word_scores)
    # Take a sum of teh RNN outputs at each step weighted by the computed scores
    memory_output = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,1)),
                     output_shape=(p['units1'],), name = "memory_output")([sentence_matrix, word_scores])

    # Merge the sentence vector and the memory output
    x = layers.merge([memory_output, sentence_vector], mode=p['memory_merge'])

    # Apply softmax
    x = layers.Dropout(p['dropout1'])(x)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(x)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersAttentionEmb(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    word_embeddings = layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                input_length=max_sent_len, weights=[embeddings],
                                mask_zero=True, trainable=False)(sentence_input)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Convert each token to a memory embedding that are leanred
    memory_embeddings = layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                input_length=max_sent_len, mask_zero=True, trainable=True,
                                  W_regularizer = regularizers.l2())(sentence_input)
    memory_embeddings = layers.Dropout(p['dropout1'])(memory_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.Embedding(output_dim=p['position_emb'], input_dim=4, input_length=max_sent_len,
                         mask_zero=True, W_regularizer = regularizers.l2(), trainable=True)(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = getattr(layers, p['rnn1'])(p['units1'], return_sequences=True, consume_less='gpu' if p['gpu'] else "cpu")(x)
    sentence_vector = getattr(layers, p['rnn1'])(p['units1'], return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu")(x)

    ### Attention ###
    # Compute a memory vector for a sentence and compute a score for each word by multiplying it with word memory embeddings
    sentence_memory = layers.Dense(embeddings.shape[1], activation="tanh")(sentence_vector)
    word_scores = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,2)),
                     output_shape=(max_sent_len,), name = "word_scores")([sentence_memory, memory_embeddings])
    word_scores = layers.Activation('softmax')(word_scores)
    memory_output = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,1)),
                     output_shape=(embeddings.shape[1],), name = "memory_output")([word_embeddings, word_scores])

    # Merge the memory output and the sentence vector
    x = layers.merge([memory_output, sentence_vector], mode=p['memory_merge'])

    # Apply softmax
    x = layers.Dropout(p['dropout1'])(x)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(x)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersSumGhosts(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    # Repeat the input 3 times as will need it once for the target entity pair and twice for the ghost pairs
    x = layers.RepeatVector(MAX_EDGES_PER_GRAPH)(sentence_input)
    word_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                                                input_length=max_sent_len, weights=[embeddings],
                                                                mask_zero=True, trainable=False))(x)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(MAX_EDGES_PER_GRAPH, max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=p['position_emb'],
                                                         input_dim=4, input_length=max_sent_len,
                                                         mask_zero=True, W_regularizer = regularizers.l2(),
                                                         trainable=True))(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = layers.wrappers.TimeDistributed(
            getattr(layers, p['rnn1'])(p['units1'], return_sequences=True,
                                       consume_less='gpu' if p['gpu'] else "cpu"))(x)
    sentence_matrix = layers.wrappers.TimeDistributed(
        getattr(layers, p['rnn1'])(p['units1'],
                                   return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu"))(x)

    # Take the vector of the sentences with the target entity pair
    layers_to_concat = []
    for i in range(MAX_EDGES_PER_GRAPH):
        sentence_vector = layers.Lambda(lambda l: l[:, i], output_shape=(p['units1'],))(sentence_matrix)
        if i == 0:
            context_vectors = layers.Lambda(lambda l: l[:, i+1:], output_shape=(MAX_EDGES_PER_GRAPH-1, p['units1']))(sentence_matrix)
        elif i == MAX_EDGES_PER_GRAPH - 1:
            context_vectors = layers.Lambda(lambda l: l[:, :i], output_shape=(MAX_EDGES_PER_GRAPH-1, p['units1']))(sentence_matrix)
        else:
            context_vectors = layers.Lambda(lambda l: K.concatenate([l[:, :i], l[:, i+1:]], axis=1), output_shape=(MAX_EDGES_PER_GRAPH-1, p['units1']))(sentence_matrix)
        if p['contex.sum'] == 'max':
            context_vector = layers.GlobalMaxPooling1D()(context_vectors)
        elif p['contex.sum'] == 'avg':
            context_vector = layers.GlobalAveragePooling1D()(context_vectors)
        else:
            context_vector = GlobalSumPooling1D()(context_vectors)
        edge_vector = layers.merge([sentence_vector, context_vector], mode="concat")
        edge_vector = layers.Reshape((1, p['units1']*2))(edge_vector)
        layers_to_concat.append(edge_vector)
    # edge_vectors = layers.Lambda(lambda l: K.stack(l), output_shape=(MAX_EDGES_PER_GRAPH-1, p['units1']*2))(layers_to_concat)
    edge_vectors = layers.Merge(mode='concat', concat_axis=1)(layers_to_concat)

    # Apply softmax
    edge_vectors = layers.Dropout(p['dropout1'])(edge_vectors)
    main_output = layers.wrappers.TimeDistributed(layers.Dense(n_out, activation = "softmax", name='main_output'))(edge_vectors)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersSumGhostsV2(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    # Repeat the input 3 times as will need it once for the target entity pair and twice for the ghost pairs
    x = layers.RepeatVector(3)(sentence_input)
    word_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                                                       input_length=max_sent_len, weights=[embeddings],
                                                                       mask_zero=True, trainable=False))(x)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(3, max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=p['position_emb'],
                                                                      input_dim=4, input_length=max_sent_len,
                                                                      mask_zero=True, W_regularizer = regularizers.l2(),
                                                                      trainable=True))(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = layers.wrappers.TimeDistributed(
            getattr(layers, p['rnn1'])(p['units1'], return_sequences=True,
                                       consume_less='gpu' if p['gpu'] else "cpu"))(x)
    sentence_matrix = layers.wrappers.TimeDistributed(
        getattr(layers, p['rnn1'])(p['units1'],
                                   return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu"))(x)

    # Take the vector of the sentences with the target entity pair
    sentence_vector = GetOutput(target_positions=[0])(sentence_matrix)
    sentence_vector = layers.Flatten()(sentence_vector)

    # Take the two vectors of the ghost entity pairs and sum them
    ghost_vectors = GetOutput(target_positions=[1,2])(sentence_matrix)
    ghost_vector = GlobalSumPooling1D()(ghost_vectors)

    # Merge the sentence and ghost vectors
    x = layers.merge([sentence_vector,ghost_vector], mode="concat")

    # Apply softmax
    x = layers.Dropout(p['dropout1'])(x)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(x)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersSumGhostsV3(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    # Repeat the input 3 times as will need it once for the target entity pair and twice for the ghost pairs
    x = layers.RepeatVector(3)(sentence_input)
    word_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                                                       input_length=max_sent_len, weights=[embeddings],
                                                                       mask_zero=True, trainable=False))(x)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(3, max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=p['position_emb'],
                                                                      input_dim=4, input_length=max_sent_len,
                                                                      mask_zero=True, W_regularizer = regularizers.l2(),
                                                                      trainable=True))(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = layers.wrappers.TimeDistributed(
            getattr(layers, p['rnn1'])(p['units1'], return_sequences=True,
                                       consume_less='gpu' if p['gpu'] else "cpu"))(x)
    sentence_matrix = layers.wrappers.TimeDistributed(
        getattr(layers, p['rnn1'])(p['units1'],
                                   return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu"))(x)

    # Take the vector of the sentences with the target entity pair
    sentence_vector = GetOutput(target_positions=[0])(sentence_matrix)
    sentence_vector = layers.Flatten()(sentence_vector)

    # Take the two vectors of the ghost entity pairs and sum them
    ghost_vectors = GetOutput(target_positions=[1,2])(sentence_matrix)
    ghost_vector = GlobalSumPooling1D()(ghost_vectors)

    ghost_vector = layers.Dense(p['units2'], activation = "tanh")(ghost_vector)

    # Merge the sentence and ghost vectors
    x = layers.merge([sentence_vector,ghost_vector], mode="concat")

    # Apply softmax
    x = layers.Dropout(p['dropout1'])(x)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(x)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersScoredGhosts(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    # Repeat the input 3 times as will need it once for the target entity pair and twice for the ghost pairs
    x = layers.RepeatVector(MAX_EDGES_PER_GRAPH)(sentence_input)
    word_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                                                       input_length=max_sent_len, weights=[embeddings],
                                                                       mask_zero=True, trainable=False))(x)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(MAX_EDGES_PER_GRAPH, max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=p['position_emb'],
                                                                      input_dim=4, input_length=max_sent_len,
                                                                      mask_zero=True, W_regularizer = regularizers.l2(),
                                                                      trainable=True))(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = layers.wrappers.TimeDistributed(
            getattr(layers, p['rnn1'])(p['units1'], return_sequences=True,
                                       consume_less='gpu' if p['gpu'] else "cpu"))(x)
    sentence_matrix = layers.wrappers.TimeDistributed(
        getattr(layers, p['rnn1'])(p['units1'],
                                   return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu"))(x)

    ### Attention over ghosts ###
    layers_to_concat = []
    for i in range(MAX_EDGES_PER_GRAPH):
        # Compute a memory vector for the target entity pair
        sentence_vector = layers.Lambda(lambda l: l[:, i], output_shape=(p['units1'],))(sentence_matrix)
        target_sentence_memory = layers.Dense(p['units1'], activation="linear", bias=False)(sentence_vector)
        if i == 0:
            context_vectors = layers.Lambda(lambda l: l[:, i+1:], output_shape=(MAX_EDGES_PER_GRAPH-1, p['units1']))(sentence_matrix)
        elif i == MAX_EDGES_PER_GRAPH - 1:
            context_vectors = layers.Lambda(lambda l: l[:, :i], output_shape=(MAX_EDGES_PER_GRAPH-1, p['units1']))(sentence_matrix)
        else:
            context_vectors = layers.Lambda(lambda l: K.concatenate([l[:, :i], l[:, i+1:]], axis=1), output_shape=(MAX_EDGES_PER_GRAPH-1, p['units1']))(sentence_matrix)
        # Compute the score between each memory and the memory of the target entity pair
        sentence_scores = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0],
                                                                       inputs[1], axes=(1,2)),
                                       output_shape=(MAX_EDGES_PER_GRAPH,))([target_sentence_memory, context_vectors])
        sentence_scores = layers.Activation('softmax')(sentence_scores)

        # Compute the final vector by taking the weighted sum of context vectors and the target entity vector
        context_vector = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,1)),
                                      output_shape=(p['units1'],))([context_vectors, sentence_scores])
        edge_vector = layers.merge([sentence_vector, context_vector], mode="concat")
        edge_vector = layers.Reshape((1, p['units1']*2))(edge_vector)
        layers_to_concat.append(edge_vector)

    edge_vectors = layers.Merge(mode='concat', concat_axis=1)(layers_to_concat)

    # Apply softmax
    edge_vectors = layers.Dropout(p['dropout1'])(edge_vectors)
    main_output = layers.wrappers.TimeDistributed(layers.Dense(n_out, activation = "softmax", name='main_output'))(edge_vectors)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersScoredGhostsV2(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    # Repeat the input 3 times as will need it once for the target entity pair and twice for the ghost pairs
    x = layers.RepeatVector(3)(sentence_input)
    word_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                                                       input_length=max_sent_len, weights=[embeddings],
                                                                       mask_zero=True, trainable=False))(x)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(3, max_sent_len,), dtype='int8', name='ghost_entity_markers')
    pos_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=p['position_emb'],
                                                                      input_dim=4, input_length=max_sent_len,
                                                                      mask_zero=True, W_regularizer = regularizers.l2(),
                                                                      trainable=True))(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = layers.wrappers.TimeDistributed(
            getattr(layers, p['rnn1'])(p['units1'], return_sequences=True,
                                       consume_less='gpu' if p['gpu'] else "cpu"))(x)
    sentence_matrix = layers.wrappers.TimeDistributed(
        getattr(layers, p['rnn1'])(p['units1'],
                                   return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu"))(x)

    ### Attention over ghosts ###
    # Compute a memory vector for the target entity pair
    target_sentence_vector = layers.Lambda(lambda l: K.gather(K.permute_dimensions(l, (1,0,2)), 0), output_shape=(p['units1'],))(sentence_matrix)
    target_sentence_vector = layers.Dense(p['units1'], activation="linear", bias=False)(target_sentence_vector)

    # Compute the score between the sentence vectors and the memory of the target entity pair
    sentence_scores = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0],
                                                          inputs[1], axes=(1,2)),
                                   name = "sentence_scores", output_shape=(3,))([target_sentence_vector, sentence_matrix])
    sentence_scores = layers.Activation('softmax')(sentence_scores)

    # Compute the final vector by taking the weighted sum of ghost vectors and the target entity vector
    x = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,1)),
                     output_shape=(p['units1'],), name = "o")([sentence_matrix, sentence_scores])

    # Apply softmax
    x = layers.Dropout(p['dropout1'])(x)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(x)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersScoredGhostsV3(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    # Repeat the input 3 times as will need it once for the target entity pair and twice for the ghost pairs
    x = layers.RepeatVector(3)(sentence_input)
    word_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                                                       input_length=max_sent_len, weights=[embeddings],
                                                                       mask_zero=True, trainable=False))(x)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(3, max_sent_len,), dtype='int8', name='ghost_entity_markers')
    pos_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=p['position_emb'],
                                                                      input_dim=4, input_length=max_sent_len,
                                                                      mask_zero=True, W_regularizer = regularizers.l2(),
                                                                      trainable=True))(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = layers.wrappers.TimeDistributed(
            getattr(layers, p['rnn1'])(p['units1'], return_sequences=True,
                                       consume_less='gpu' if p['gpu'] else "cpu"))(x)
    sentence_matrix = layers.wrappers.TimeDistributed(
        getattr(layers, p['rnn1'])(p['units1'],
                                   return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu"))(x)

    ### Attention over ghosts ###
    # Compute a memory vector for the target entity pair
    target_sentence_vector = GetOutput([0])(sentence_matrix)
    target_sentence_vector = layers.Flatten()(target_sentence_vector)
    target_sentence_memory = layers.Dense(p['units1'], activation="linear", bias=False)(target_sentence_vector)

    ghost_vectors = GetOutput(target_positions=[1,2])(sentence_matrix)

    # Compute the score between each memory and the memory of the target entity pair
    sentence_scores = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0],
                                                                   inputs[1], axes=(1,2)),
                                   name = "sentence_scores", output_shape=(2,))([target_sentence_memory, ghost_vectors])
    sentence_scores = layers.Activation('softmax')(sentence_scores)

    # Compute the final vector by taking the weighted sum of ghost vectors and the target entity vector
    ghost_vector = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,1)),
                     output_shape=(p['units1'],), name = "o")([ghost_vectors, sentence_scores])

    x = layers.merge([target_sentence_vector,ghost_vector], mode="concat")

    # Apply softmax
    x = layers.Dropout(p['dropout1'])(x)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(x)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersScoredGhostsV4(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    # Repeat the input 3 times as will need it once for the target entity pair and twice for the ghost pairs
    x = layers.RepeatVector(3)(sentence_input)
    word_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                                                       input_length=max_sent_len, weights=[embeddings],
                                                                       mask_zero=True, trainable=False))(x)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(3, max_sent_len,), dtype='int8', name='ghost_entity_markers')
    pos_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=p['position_emb'],
                                                                      input_dim=4, input_length=max_sent_len,
                                                                      mask_zero=True, W_regularizer = regularizers.l2(),
                                                                      trainable=True))(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = layers.wrappers.TimeDistributed(
            getattr(layers, p['rnn1'])(p['units1'], return_sequences=True,
                                       consume_less='gpu' if p['gpu'] else "cpu"))(x)
    sentence_matrix = layers.wrappers.TimeDistributed(
        getattr(layers, p['rnn1'])(p['units1'],
                                   return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu"))(x)

    ### Attention over ghosts ###
    # Compute a memory vector for the target entity pair
    target_sentence_vector = GetOutput([0])(sentence_matrix)
    target_sentence_vector = layers.Flatten()(target_sentence_vector)
    target_sentence_memory = layers.Dense(p['units1'], activation="linear", bias=False)(target_sentence_vector)

    ghost_vectors = GetOutput(target_positions=[1,2])(sentence_matrix)

    # Compute the score between each memory and the memory of the target entity pair
    sentence_scores = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0],
                                                                   inputs[1], axes=(1,2)),
                                   name = "sentence_scores", output_shape=(2,))([target_sentence_memory, ghost_vectors])
    sentence_scores = layers.Activation('softmax')(sentence_scores)

    # Compute the final vector by taking the weighted sum of ghost vectors and the target entity vector
    ghost_vector = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,1)),
                                output_shape=(p['units1'],), name = "o")([ghost_vectors, sentence_scores])

    x = layers.merge([target_sentence_vector,ghost_vector], mode="concat")

    x = layers.Dense(p['units1'], activation = "tanh")(x)

    # Apply softmax
    x = layers.Dropout(p['dropout1'])(x)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(x)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

def model_RnnMarkersAttentionEmbScoredGhosts(p, embeddings, max_sent_len, n_out):
    print("Parameters:", p)

    # Take sentence encoded as indices and convert it to embeddings
    sentence_input = layers.Input(shape=(max_sent_len,), dtype='int32', name='sentence_input')
    # Repeat the input 3 times as will need it once for the target entity pair and twice for the ghost pairs
    x = layers.RepeatVector(3)(sentence_input)
    word_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                                                input_length=max_sent_len, weights=[embeddings],
                                                                mask_zero=True, trainable=False))(x)
    word_embeddings = layers.Dropout(p['dropout1'])(word_embeddings)

    # Convert each token to a memory embedding that are learned
    memory_embeddings = layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                                  input_length=max_sent_len, mask_zero=True, trainable=True,
                                  W_regularizer = regularizers.l2())(sentence_input)
    memory_embeddings = layers.Dropout(p['dropout1'])(memory_embeddings)

    # Take token markers that identify entity positions, convert to position embeddings
    entity_markers = layers.Input(shape=(3, max_sent_len,), dtype='int8', name='entity_markers')
    pos_embeddings = layers.wrappers.TimeDistributed(layers.Embedding(output_dim=p['position_emb'],
                                                         input_dim=4, input_length=max_sent_len,
                                                         mask_zero=True, W_regularizer = regularizers.l2(),
                                                         trainable=True))(entity_markers)

    # Merge word and position embeddings and apply the specified amount of RNN layers
    x = layers.merge([word_embeddings, pos_embeddings], mode="concat")
    for i in range(p["rnn1_layers"]-1):
        x = layers.wrappers.TimeDistributed(
            getattr(layers, p['rnn1'])(p['units1'], return_sequences=True,
                                       consume_less='gpu' if p['gpu'] else "cpu"))(x)
    sentence_matrix = layers.wrappers.TimeDistributed(
        getattr(layers, p['rnn1'])(p['units1'],
                                   return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu"))(x)

    ### Attention ###
    # Take the vector of the sentences with the target entity pair
    sentence_vector = GetOutput(target_positions=[0])(sentence_matrix)
    sentence_vector = layers.Flatten()(sentence_vector)

    # Compute a memory vector for a sentence and compute a score for each word by multiplying it with word memory embeddings
    sentence_memory = layers.Dense(embeddings.shape[1], activation="tanh")(sentence_vector)
    word_scores = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,2)),
                 output_shape=(max_sent_len,))([sentence_memory, memory_embeddings])
    word_scores = layers.Activation('softmax')(word_scores)
    # We have to map tokens to embeddings here again (doesn't affect anything) due to a Theano bug/our bug
    word_embeddings = layers.Embedding(output_dim=embeddings.shape[1], input_dim=embeddings.shape[0],
                          input_length=max_sent_len, weights=[embeddings],
                          mask_zero=True, trainable=False)(sentence_input)
    # Take a weighted sum of words here
    memory_output = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,1)),
                     output_shape=(embeddings.shape[1],))([word_embeddings, word_scores])

    ### Attention over ghosts ###
    # Compute a memory vector for each entity pair
    sentence_memories = layers.wrappers.TimeDistributed(
        getattr(layers, p['rnn1'])(50,
                                   return_sequences=False, consume_less='gpu' if p['gpu'] else "cpu"))(x)
    # Compute the score between each memory and the memory of the target entity pair
    sentence_scores = layers.Lambda(lambda l: K.batch_dot(K.gather(K.permute_dimensions(l, (1,0,2)),0), l, axes=(1,2)),
                      name = "a", output_shape=(3,))(sentence_memories)
    sentence_scores = layers.Activation('softmax')(sentence_scores)

    # Compute the final vector by taking the weighted sum of ghost vectors and the target entity vector
    ghost_vector = layers.Merge(mode=lambda inputs: K.batch_dot(inputs[0], inputs[1], axes=(1,1)),
                     output_shape=(p['units1'],), name = "o")([sentence_vector, sentence_scores])

    # merge the output of the weighted sum of ghost vectors and the weighted sum of words
    x = layers.merge([memory_output, ghost_vector], mode='concat')

    # Apply softmax
    x = layers.Dropout(p['dropout1'])(x)
    main_output = layers.Dense(n_out, activation = "softmax", name='main_output')(x)

    model = models.Model(input=[sentence_input, entity_markers], output=[main_output])
    model.compile(optimizer=p['optimizer'], loss='categorical_crossentropy', metrics=['accuracy'])

    return model

class GetOutput(layers.Layer):
    def __init__(self, target_positions=[], **kwargs):
        self.supports_masking = False
        self.target_positions = target_positions
        super(GetOutput, self).__init__(**kwargs)

    def call(self, x, mask=None):
        if not self.target_positions:
            return x
        return K.permute_dimensions(K.gather(K.permute_dimensions(x, [1,0,2]), self.target_positions), [1,0,2])

    def compute_mask(self, x, mask=None):
        return None

    def get_output_shape_for(self, input_shape):
        return (input_shape[0], len(self.target_positions) ,input_shape[2])

    def get_config(self):
        config = {'target_positions': self.target_positions}
        base_config = super(GetOutput, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

class GlobalSumPooling1D(layers.Layer):

    def __init__(self, **kwargs):
        super(GlobalSumPooling1D, self).__init__(**kwargs)
        self.input_spec = [layers.InputSpec(ndim=3)]

    def get_output_shape_for(self, input_shape):
        return (input_shape[0], input_shape[2])

    def call(self, x, mask=None):
        return K.sum(x, axis=1)

class MaskedConvolution1D(layers.Convolution1D):
    def __init__(self, **kwargs):
        self.supports_masking = True
        super(MaskedConvolution1D, self).__init__(**kwargs)

    def compute_mask(self, x, mask=None):
        return mask

class MaskedGlobalMaxPooling1D(layers.pooling._GlobalPooling1D):
    def __init__(self, **kwargs):
        self.supports_masking = True
        super(MaskedGlobalMaxPooling1D, self).__init__(**kwargs)

    def call(self, x, mask=None):
        if mask == None:
            return K.max(x, axis = 1)
        else:
            return K.max(K.switch(mask[:,:,np.newaxis], x, -np.inf ), axis = 1)

    def compute_mask(self, x, mask=None):
        return None

def get_negative_edges(g, limit=1):
    """

    :param g: graphs a dictionary
    :return: a list of negative edges
    >>> get_negative_edges({'edgeSet': [{'kbID': 'P397', 'left': [8], 'right': [23]}, \
    {'kbID': 'P376', 'left': [80], 'right': [8]}], 'vertexSet': [{'tokenpositions': [8]}, {'tokenpositions': [23]}, {'tokenpositions': [80]}]}) \
    == [{'left': [23], 'kbID': 'P0', 'right': [80]}]
    True
    """
    vertex_pairs = itertools.combinations(g["vertexSet"], 2)
    existing_edges = [p for e in g["edgeSet"] for p in [(e['left'], e['right']), (e['right'], e['left'])]]
    negative_edges = []
    for vertex_pair in vertex_pairs:
        left_right = (vertex_pair[0]['tokenpositions'], vertex_pair[1]['tokenpositions'])
        if left_right not in existing_edges:
            negative_edges.append({'kbID': 'P0', 'left': left_right[0], 'right': left_right[1]})
    if len(negative_edges) > limit:
        negative_edges = np.random.choice(negative_edges, limit, replace=False)
    return list(negative_edges)

def to_indices(graphs, word2idx, property2idx, max_sent_len, replace_entities_with_unkown = False, mode='train', **kwargs):
    """
    :param graphs:
    :param word2idx:
    :param property2idx:
    :param max_sent_len:
    :return:
    """
    num_edges = len([e for g in graphs for e in g['edgeSet'] if e['kbID'] not in property_blacklist])
    print("Dataset number of edges: {}".format(num_edges))
    sentences_matrix = np.zeros((num_edges, max_sent_len), dtype="int32")
    entity_matrix = np.zeros((num_edges, max_sent_len), dtype="int8")
    y_matrix = np.zeros(num_edges, dtype="int16")
    index = 0
    for g in tqdm.tqdm(graphs, ascii=True):
        token_ids = embedding_utils.get_idx_sequence(g["tokens"], word2idx)
        if len(token_ids) > max_sent_len:
            token_ids = token_ids[:max_sent_len]
        for edge in g["edgeSet"]:
            if edge['kbID'] not in property_blacklist:
                sentences_matrix[index, :len(token_ids)] = \
                    [word2idx[embedding_utils.unknown] if i in edge["left"] + edge["right"] else t for i, t in enumerate(token_ids)] \
                        if replace_entities_with_unkown else token_ids
                entity_matrix[index, :len(token_ids)] = \
                    [m for _, m in graph_utils.get_entity_indexed_vector(token_ids, edge, mode="mark-bi")]
                if mode == "train":
                    _, property_kbid, _ = graph_utils.edge_to_kb_ids(edge, g)
                    property_kbid = property2idx.get(property_kbid, property2idx[embedding_utils.unknown])
                    y_matrix[index] = property_kbid
                index += 1
    return [sentences_matrix, entity_matrix, y_matrix]

MAX_EDGES_PER_GRAPH = 7

def to_indices_with_real_entities(graphs, word2idx, property2idx, max_sent_len, mode='train', **kwargs):
    """
    :param graphs:
    :param word2idx:
    :param property2idx:
    :param max_sent_len:
    :return:
    """
    graphs_to_process = []
    for g in graphs:
        if len(g['edgeSet']) > 0:
            if len(g['edgeSet']) <= MAX_EDGES_PER_GRAPH:
                graphs_to_process.append(g)
            else:
                for i in range(0, len(g['edgeSet']), MAX_EDGES_PER_GRAPH):
                    graphs_to_process.append({"tokens": g["tokens"], "edgeSet": g["edgeSet"][i:i+ MAX_EDGES_PER_GRAPH]})
    graphs = graphs_to_process
    sentences_matrix = np.zeros((len(graphs), max_sent_len), dtype="int32")
    entity_matrix = np.zeros((len(graphs), MAX_EDGES_PER_GRAPH, max_sent_len), dtype="int8")
    y_matrix = np.zeros((len(graphs), MAX_EDGES_PER_GRAPH), dtype="int16")
    for index, g in enumerate(tqdm.tqdm(graphs, ascii=True)):
        token_ids = embedding_utils.get_idx_sequence(g["tokens"], word2idx)
        if len(token_ids) > max_sent_len:
            token_ids = token_ids[:max_sent_len]
        sentences_matrix[index, :len(token_ids)] = token_ids
        for j, edge in enumerate(g["edgeSet"][:MAX_EDGES_PER_GRAPH]):
            entity_matrix[index, j, :len(token_ids)] = \
                [m for _, m in graph_utils.get_entity_indexed_vector(token_ids, edge, mode="mark-bi")]
            _, property_kbid, _ = graph_utils.edge_to_kb_ids(edge, g)
            property_kbid = property2idx.get(property_kbid, property2idx[embedding_utils.unknown])
            y_matrix[index, j] = property_kbid
    return sentences_matrix, entity_matrix, y_matrix

def graphs_for_evaluation(graphs, graphs_tagged):
    for_evaluation = []
    for i, g in enumerate(tqdm.tqdm(graphs, ascii=True, ncols=100)):
        for edge in g["edgeSet"]:
            new_g = {"edgeSet": [edge], "tokens": g['tokens']}
            entities = [ne for ne, t in graph.extract_entities(graphs_tagged[i])]
            entities += [edge['left'], edge['right']]
            new_g['vertexSet'] = [{'tokenpositions': ne} for ne in entities]
            new_g['edgeSet'].extend(get_negative_edges(new_g, limit=6))
            for_evaluation.append(new_g)
    return for_evaluation

def to_indices_with_ghost_entities(graphs, word2idx, property2idx, max_sent_len, embeddings, **kwargs):
    sentences_matrix, entity_matrix, y_matrix = to_indices(graphs, word2idx, property2idx, max_sent_len, **kwargs)
    ghost_entity_matrix = create_ghost_edges(sentences_matrix, entity_matrix, embeddings)
    entity_matrix = entity_matrix.reshape((entity_matrix.shape[0], 1, entity_matrix.shape[1]))
    entity_matrix = np.concatenate([entity_matrix, ghost_entity_matrix], axis = 1)
    return [sentences_matrix, entity_matrix, y_matrix]

def to_indices_with_relative_positions(graphs, word2idx, property2idx, max_sent_len, position2idx, **kwargs):
    num_edges = len([e for g in graphs for e in g['edgeSet']])
    sentences_matrix = np.zeros((num_edges, max_sent_len), dtype="int32")
    entity_matrix = np.zeros((num_edges, 2, max_sent_len), dtype="int8")
    y_matrix = np.zeros(num_edges, dtype="int16")
    index = 0
    max_entity_index = max_sent_len - 1
    for g in tqdm.tqdm(graphs, ascii=True):
        token_ids = embedding_utils.get_idx_sequence(g["tokens"], word2idx)
        if len(token_ids) > max_sent_len:
            token_ids = token_ids[:max_sent_len]
        for edge in g["edgeSet"]:
            sentences_matrix[index, :len(token_ids)] = token_ids
            _, property_kbid, _ = graph_utils.edge_to_kb_ids(edge, g)
            property_kbid = property2idx[property_kbid]
            entity_vector = graph_utils.get_entity_indexed_vector(token_ids, edge, mode="position")
            entity_vector = [(-max_entity_index if m1 < -max_entity_index else max_entity_index if m1 > max_entity_index else m1,
                              -max_entity_index if m2 < -max_entity_index else max_entity_index if m2 > max_entity_index else m2) for _, m1,m2  in entity_vector]
            entity_matrix[index, :, :len(token_ids)] = [[position2idx[m] for m,_  in entity_vector],[position2idx[m] for _, m  in entity_vector]]

            y_matrix[index] = property_kbid
            index += 1
    return [sentences_matrix, entity_matrix, y_matrix]

def softmax(x):
    e_x = np.exp(x)
    return e_x / e_x.sum(axis=0)

def create_ghost_edges(sentences_matrix, entity_matrix, embeddings):
    ghost_matrix = np.zeros((entity_matrix.shape[0], 2, entity_matrix.shape[1]))
    for i in range(sentences_matrix.shape[0]):
        entity_vector = entity_matrix[i][entity_matrix[i].nonzero()]
        sentence_vector = sentences_matrix[i][sentences_matrix[i].nonzero()]
        e1_one_hot = entity_vector == 2
        e2_one_hot = entity_vector == 3
        entity_embs = np.dot(np.asarray([e1_one_hot,e2_one_hot]), embeddings[sentence_vector])

        e1_index = np.nonzero(e1_one_hot)[0]
        e2_index = np.nonzero(e2_one_hot)[0]
        entity_attention = np.dot(entity_embs, embeddings[sentence_vector].T)
        entity_attention = softmax(entity_attention.T).T

        entity_attention[:,[np.concatenate([e1_index, e2_index])]] = -np.Inf
        ghost_markers = np.tile(entity_vector, (2,1))
        ghost_markers[0][e1_index] =  1
        ghost_markers[1][e2_index] =  1
        if entity_attention.shape[-1] > 0:
            selected_entities = np.argmax(entity_attention, axis=-1)
            ghost_markers[0][selected_entities[0]] = 2
            ghost_markers[1][selected_entities[1]] = 3
            ghost_matrix[i,:,:entity_vector.shape[0]] = ghost_markers

    return ghost_matrix

if __name__ == "__main__":
    # Testing
    import doctest
    print(doctest.testmod())


text:
# -*- coding: utf-8 -*-
"""
smoothing.py contains the main smoothing function, which works by convolving a signal with a smoothing kernel,
a signals function which acts as a cache for kernels, as well as the hamming_smooth function, which is the only
one currently used by external files, providing a simplified interface for smoothing with hamming kernels.
"""
from __future__ import division, unicode_literals, print_function

import numpy as np

def smooth(signal, kernel):
    """
    Generic smoothing function, smooths by convolving one signal with another.

    :param signal: input signal to be smoothed
    :type signal: numpy.ndarray
    :param kernel: smoothing kernel to be used. will be normalized to :math:`\sum=1`
    :type kernel: numpy.ndarray
    :return: The signal convolved with the kernel
    :rtype: numpy.ndarray

    >>> smooth(np.array([0, 0, 0, 0, 1, 0, 0, 0, 0]), np.ones(3))
    array([0.        , 0.        , 0.        , 0.        , 0.33333333,
           0.33333333, 0.33333333, 0.        , 0.        ])
    """

    return np.convolve(
        kernel / kernel.sum(),
        np.r_[signal[kernel.size - 1:0:-1], signal, signal[-1:-kernel.size:-1]],
        mode='valid')[kernel.size // 2 - 1:-kernel.size // 2][0:len(signal)]

def hamming_smooth(signal, window_width, no_cache=False):
    """
    Smooths a signal by convolving with a hamming window of given width. Caches by the hamming windows by default.

    :param signal: input signal to be smoothed
    :type signal: numpy.ndarray
    :param window_width: window width for the hamming kernel
    :type window_width: int
    :param no_cache: default `False`, disables caching, *e.g.*, for non-standard window sizes
    :type no_cache: bool
    :return: the smoothed signal
    :rtype: numpy.ndarray

    >>> hamming_smooth(np.array([0, 0, 0, 0, 1, 0, 0, 0, 0]), 3)
    array([0.        , 0.        , 0.        , 0.        , 0.06896552,
           0.86206897, 0.06896552, 0.        , 0.        ])
    """

    if len(signal) == 1:
        return signal

    if len(signal) < window_width:
        window_width = len(signal)
        no_cache = True

    return smooth(signal,
                  np.hamming(window_width) if no_cache
                  else signals(np.hamming, window_width))

_signals = {}

# TODO: In a Python3 only version, this could be replaced by decorating calls with a @functools.lru_cache
def signals(function, parameters):
    """
    Signal cache helper function. Either retrieves or creates and stores a signal which can be created by calling
    the given function with the given parameters.

    :param function: Window function to be called
    :type function: callable
    :param parameters: Parameters to be passed to the function
    :type parameters: \*any
    :return: function(\*parameters)
    :rtype: dependent on function

    >>> signals(np.ones, 3)
    array([1., 1., 1.])
    """
    global _signals
    if function not in _signals:
        _signals[function] = {}
    if not type(parameters) == tuple:
        parameters = (parameters,)
    sf = _signals[function]
    if parameters not in sf:
        result = function(*parameters)
        result = result.astype(np.float64)
        result.flags.writeable = False
        sf[parameters] = result
        return result
    else:
        return sf[parameters]

ext: py

max_stars_repo_name: csachs/molyso

max_issues_repo_name: csachs/molyso

max_forks_repo_name: csachs/molyso

reason: import numpy


text:
import abc
import collections

import torch

import numpy as np

import pytorch_privacy.utils.torch_nest_utils as nest
import pytorch_privacy.utils.numpy_nest_utils as np_nest

class DPQuery(abc.ABC):
    """ General class for a query applied to data in a DP fashion.
    Terminology derived from definitions in https://arxiv.org/abs/1812.06210
    """

    def set_ledger(self, ledger):
        """ Sets the ledger for this query to record privacy events in.
        :param ledger: A 'PrivacyLedger'.
        """

        del ledger
        raise TypeError(
            'DPQuery typ %s does not support set_ledger.' % type(self).__name__
        )

    def initial_global_state(self):
        """ Initial state for the global settings of the DPQuery. """

        return ()

    def derive_sample_params(self, global_state):
        """ Given some global state, derive the parameters to use for the next sample.

        :param global_state: A global state of the DPQuery.
        :return Parameters to use in the next sample.
        """

        del global_state
        return ()

    @abc.abstractmethod
    def initial_sample_state(self, param_groups):
        """ Returns an initial state to use at the start of the next sample.

        :param param_groups: The param_groups to use as a template for the blank state.
        :return: An initial sample state.
        """

    def preprocess_record(self, params, record):
        """ Preprocess a single record.

        Applies to a single clients record, this could be clipping a vector to a fixed L2
        norm.
        :param params: The parameters for this sample, in DP-SGD, the L2 bound.
        :param record: The record to process, in DP-SGD, a single mircobatch gradient.
        :return: A structure of tensors to apply.
        """

        del params
        return record

    @abc.abstractmethod
    def accumulate_preprocessed_record(self, sample_state, record):
        """ Accumulate a single record into the current sample state.

        Does simple aggregation of the recodrs, usually just summing.

        :param sample_state: The current sample state e.g. in DP-SGD the accumulated
        clipped gradients so far.
        :param record: The new record to accumulate.
        :return: The updated sample state.
        """

    def accumulate_record(self, params, sample_state, record):
        """ Accumulate a new record into the sample state.

        Simple delegation function to other defined functions.

        :param params: The sample parameters, e.g. clipping bound in DP-SGD.
        :param sample_state: The current sample state.
        :param record: The new record to accumulate.
        :return: The updated sample state with extra information about the record
        """
        preprocessed_record = self.preprocess_record(params, record)
        return self.accumulate_preprocessed_record(sample_state, preprocessed_record)

    @abc.abstractmethod
    def merge_sample_states(self, sample_state_1, sample_state_2):
        """ Merges two sample_states together.

        :param sample_state_1: The first sample state.
        :param sample_state_2: The second sample state.
        :return:  The merged sample states.
        """

    @abc.abstractmethod
    def get_noised_result(self, sample_state, global_parameters):
        """ Applies privacy noise after all the samples have been accumulated
        :param sample_state: The accumulated sample stata
        :param global_parameters: The current global parameters
        :return: A tuple (results, new_global_state) that contains the result of the
        query and the new query global state
        """

class SumAggregationDPQuery(DPQuery):
    """ Base class for when a DPQuery aggregates via summation """

    def initial_sample_state(self, param_groups):
        """ Return state of zeros the same shape as the parameter groups."""
        return nest.map_structure(torch.zeros_like, param_groups)

    def accumulate_preprocessed_record(self, sample_state, record):
        return nest.map_structure(torch.add, sample_state, record)

    def merge_sample_states(self, sample_state_1, sample_state_2):
        return nest.map_structure(torch.add, sample_state_1, sample_state_2)

max_stars_repo_name: MJHutchinson/PytorchPrivacy

max_issues_repo_name: MJHutchinson/PytorchPrivacy

max_forks_repo_name: MJHutchinson/PytorchPrivacy


text:
from atomic.analytic.acwrapper import ACWrapper
import json
import pandas as pd
import numpy as np

class BeliefDiffWrapper(ACWrapper):
    def __init__(self, agent_name, world=None, **kwargs):
        super().__init__(agent_name, world, **kwargs)
        self.topic_handlers = {
            'trial': self.handle_trial,
            'agent/ac/belief_diff': self.handle_msg,
            'agent/ac/threat_room_communication': self.ignore_msg,
            'agent/ac/victim_type_communication': self.ignore_msg,
            'agent/ac/threat_room_coordination': self.handle_threat}
        self.data = pd.DataFrame()

    def handle_msg(self, message, data, mission_time):
        overall_pos = data['room_id'].index('overall')
        new_data = {'Timestamp': mission_time}
        for field, value in data.items():
            if isinstance(value, list) and field != 'room_id':
                new_data[field] = value[overall_pos]
        self.last = pd.DataFrame([new_data])
        self.last['Trial'] = self.trial
        self.data = pd.concat([self.data, self.last], ignore_index=True)
        return [new_data]

    def handle_threat(self, message, data, mission_time):
        new_data = []
        if data['wait_time'][-1] != float('Infinity'):
            # For now, wait until the threat has been resolved before storing data
            new_data.append({'Player': data['threat_activation_player'][-1].split('_')[0].capitalize(),
                             'Timestamp': mission_time,
                             'wait_time': int(data['wait_time'][-1]),
                             'threat_activation_time': data['threat_activation_time'][-1],
                             'threat_room': data['room_id'][-1],
                             'threshold': data.get('threshold', data['threshold:'])})
            self.last = pd.DataFrame(new_data)
            self.last['Trial'] = self.trial
            self.data = pd.concat([self.data, self.last], ignore_index=True)
            return new_data


text:
#!/usr/bin/env python
# coding: utf-8

# In[61]:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
get_ipython().run_line_magic('matplotlib', 'inline')

df_train=pd.read_csv("HEART.csv")
print(df_train)

# In[51]:

#Display attributes in the data set.
attribute=[]
#check the decoration
attribute=df_train.columns
print(attribute)
print(len(attribute))

# In[68]:

#Describe the attributes name, count no of values, and find min, max, data type, range, quartile, percentile, box plot and outliers.
for x in attribute:
#descriptive statistics summary
    print(df_train[x].describe())
    print(" ")

# In[76]:

#Describe the attributes name, count no of values, and find min, max, data type, range, quartile, percentile, box plot and outliers.
for x in attribute:
    #Boxplot
    sns.boxplot(df_train[x])
    sns.despine()

# In[92]:

#Give visualization of statistical description of data – in form of histogram, scatter plot, pie chart
#histogram
for x in attribute:
    plt.hist(df_train[x])
    plt.title(x)
    plt.show()

# In[89]:

#Give visualization of statistical description of data – in form of histogram, scatter plot, pie chart
#scatterplot
for x in attribute:
    plt.scatter(df_train[x],df_train[x])
    plt.xlabel(x)
    plt.ylabel(x)
    plt.show()

# In[ ]:

#Give visualization of statistical description of data – in form of histogram, scatter plot, pie chart
#piechart
for x in attribute:
    test=df_train.groupby([x]).count()
    print(type(test))
    for i in test:
        plt.pie(test[i],labels=test[i])
        plt.title(x)
        plt.show()

# In[80]:

#correlation matrix
corrmat = df_train.corr()
f, ax = plt.subplots(figsize=(12, 9))
sns.heatmap(corrmat, vmax=.8, square=True)

# In[67]:

#Identify missing values and outlier and fill them with average.
for x in attribute:
    #Using numpy mean function to calculate the mean value
    meanAge = np.mean(df_train[x])
 #replacing missing values in the DataFrame
    df_train[x] = df_train[x].fillna(meanAge)

max_stars_repo_name: sihaanssr/semVI

max_issues_repo_name: sihaanssr/semVI

max_forks_repo_name: sihaanssr/semVI


text:
import os

from numba import *
from numba import error

import numpy as np

@autojit(backend='ast', locals=dict(value=struct(a=char.pointer(), b=int_)))
def struct_local():
    value.a = "foo"
    value.b = 10
    return value.a, value.b

def test_struct_locals():
    result = struct_local()
    assert result == ("foo", 10), result

@autojit(backend='ast', locals=dict(value=struct(a=char.pointer(), b=int_)))
def struct_indexing_strings():
    value['a'] = "foo"
    value['b'] = 10
    return value['a'], value['b']

@autojit(backend='ast', locals=dict(value=struct(a=char.pointer(), b=int_)))
def struct_indexing_ints():
    value[0] = "foo"
    value[1] = 10
    return value[0], value[1]

def test_struct_indexing():
    assert struct_indexing_strings() == ("foo", 10)
    assert struct_indexing_ints() == ("foo", 10)

# ----------------

@autojit(backend='ast')
def record_array(array):
    array[0].a = 4
    array[0].b = 5.0

def test_record_array():
    struct_type = struct([('a', int32), ('b', double)])
    struct_dtype = struct_type.get_dtype()

    array = np.empty((1,), dtype=struct_dtype)
    record_array(array)
    assert array[0]['a'] == 4, array[0]
    assert array[0]['b'] == 5.0, array[0]

# ----------------

struct_type = struct([('a', int_), ('b', double)])

@autojit(backend='ast', locals=dict(value=struct_type))
def coerce_to_obj():
    value.a = 10
    value.b = 20.2
    return object_(value)

def test_coerce_to_obj():
    print coerce_to_obj()

if __name__ == "__main__":
    test_struct_locals()
    test_record_array()
    test_coerce_to_obj()
    test_struct_indexing()

max_stars_repo_name: aseyboldt/numba

max_issues_repo_name: aseyboldt/numba

max_forks_repo_name: aseyboldt/numba

reason: import numpy,from numba


text:
"""
    Voxelizes and caches the protein active sites sdf file.
    Stores data in hdf5 file.

    SYSTEM ARGUMENTS
    1) Path to DIRECTORY to store the voxelized active-site hdf5 file
    2) Path to DIRECTORY containing the electron electron clouds
    3) Complete path to active-site pdb FILE
    4) Output file name for hdf5 file (Do not include .h5)
"""
import pybel
import numpy as np
import h5py
import os
import sys
from math import ceil

"""
outDirectory = Output DIRECTORY
eDirectory = ElectronClouds DIRECTORY
poseFile = Protein PDB FILE
outName = Name of output hdf5 file
"""

def cacher(outDirectory, eDirectory, poseFile, outName):
    coords = [] #nucleus xyz location
    aNum = []  #elements atomic number
    ePos = [] #electron coordinateds in relation to nuclei
    customXTransformation = 0 #in Angstroms
    customYTransformation = 0 #in Angstroms
    customZTransformation = 7.5 #in Angstroms

    """
        Reads in the active site pdb file and retrieves all atom (x,y,z)
        coordinates, all atomic numbers and the interation energy of the
        ligand/protien interaction.
    """
    active = pybel.readfile("pdb", poseFile)
    for mol in active:
        for atom in mol:
            coords.append(atom.coords)
            aNum.append(atom.atomicnum)

    """
        Places electron cloud around each ligand atom.
    """
    os.chdir(eDirectory)
    for i in range(len(coords)):
        cloudFile = open(getAtomType(aNum[i]) + ".txt", 'r')
        for line in cloudFile:
            split = [x.strip() for x in line.split(',')]
            tempx = ceil((coords[i][0] + float(split[0])) * 100) / 100.0
            tempy = ceil((coords[i][1] + float(split[1])) * 100) / 100.0
            tempz = ceil((coords[i][2] + float(split[2])) * 100) / 100.0
            chan = gNum(aNum[i])
            ePos.append(tuple([tempx,tempy,tempz,chan]))

    """
        Finds the minimum values of the particles in order to transform the
        ligand/molecule to octant 1
    """
    minX = min(ePos, key = lambda t: t[0])[0]
    minY = min(ePos, key = lambda t: t[1])[1]
    minZ = min(ePos, key = lambda t: t[2])[2]

    """
        Transforms all electrons into octant 1
    """
    transformedElectrons = []
    for i in range(len(ePos)):
        tempx = ceil((ePos[i][0] - minX + customXTransformation) * 100) / 100.0
        tempy = ceil((ePos[i][1] - minY + customYTransformation) * 100) / 100.0
        tempz = ceil((ePos[i][2] - minZ + customZTransformation) * 100) / 100.0
        transformedElectrons.append(tuple([tempx,tempy,tempz,ePos[i][3]]))

    """
    Saves all transformations applied to the active-site. Transformations are
    stored inside hdf5 file and applied to each ligand to keep keep Transformations
    consistant.
    """
    activeMinX = minX - customXTransformation
    activeMinY = minY - customYTransformation
    activeMinZ = minZ - customZTransformation
    activeMinTuple = [activeMinX,activeMinY,activeMinZ]

    #Initializes a matrix of proper dimensions and populates with voxelized protein data
    a = np.zeros((voxelLWH, voxelLWH, voxelLWH, 6))
    voxelizedActive = voxData(a, transformedElectrons)

    #Stores transforms and voxelized protein data to outputted hdf5 file
    os.chdir(outDirectory)
    hf = h5py.File(outName+'.h5', 'w')
    hf.create_dataset('activeCacheMatrix', data=voxelizedActive)
    hf.create_dataset('activeCacheTransformations', data=activeMinTuple)
    hf.close()

"""
    Scales the coords to the desired resolution (Angstroms/Voxel)
"""
def upResCalculation(value):
    return int((value-(value % voxelRes)) * (1/voxelRes))

"""
    Adds electron counts of the ligand into protein matrix
"""
def voxData(matrix, eList):
    for i in range(len(eList)):
        vx = upResCalculation(eList[i][0])
        vy = upResCalculation(eList[i][1])
        vz = upResCalculation(eList[i][2])
        vt = eList[i][3]
        matrix[vx,vy,vz,vt] += 1
    return matrix

"""
    return the elements symbol based on the atomic number
"""
def getAtomType(num):
    typeTuple = [(1,'H'),(6,'C'),(7,'N'),(8,'O'),(9,'F'),(16,'S')]
    dic = dict(typeTuple)
    return dic[num]

"""
    Assigns each element type a channel value for the output matrix
"""
def gNum(anum):
    typeTuple = [(1,0),(6,1),(7,2),(8,3),(9,4),(16,5)]
    dic = dict(typeTuple)
    return dic[anum]

if __name__ == "__main__":
    voxelRes = .5 #cubic width of voxels
    voxelLWH = 72 #width lenght and height of the voxel grid
    cacher(str(sys.argv[1]), str(sys.argv[2]), str(sys.argv[3]), str(sys.argv[4]))

max_stars_repo_name: nickpavini/OpeNNdd

max_issues_repo_name: nickpavini/OpeNNdd

max_forks_repo_name: nickpavini/OpeNNdd