# Path: preimage/utils/position.py
# def compute_position_weights(position_index, max_position, sigma_position):
#     position_penalties = numpy.array([(position_index - j) ** 2 for j in range(max_position)], dtype=numpy.float)
#     position_penalties /= -2. * (sigma_position ** 2)
#     return numpy.exp(position_penalties)
# 
# Path: preimage/utils/alphabet.py
# def get_n_gram_to_index(alphabet, n):
#     n_grams = get_n_grams(alphabet, n)
#     indexes = numpy.arange(len(n_grams))
#     n_gram_to_index = dict(zip(n_grams, indexes))
#     return n_gram_to_index
# 
# def get_n_grams(alphabet, n):
#     n = int(n)
#     if n <= 0:
#         raise InvalidNGramLengthError(n)
#     n_grams = [''.join(n_gram) for n_gram in product(alphabet, repeat=n)]
#     return n_grams


import numpy
from preimage.inference.bound_calculator import OCRMinBoundCalculator, MaxBoundCalculator, PeptideMinBoundCalculator
from preimage.inference.node_creator import NodeCreator
from preimage.utils.position import compute_position_weights
from preimage.utils.alphabet import get_n_gram_to_index, get_n_grams


def get_gs_similarity_node_creator(alphabet, n, graph, graph_weights, y_length, gs_kernel):
    """Create the bounds and the node creator for the branch and bound search of the generic string kernel.

    Takes in account the position and the n-gram penalties when comparing strings (sigma_p and sigma_c in the
    gs kernel).

    Parameters
    ----------
    alphabet : list
        List of letters.
    n : int
        N-gram length.
    graph : array, shape = [n_partitions, len(alphabet)**n]
        Array representation of the graph. graph[i, j] represents the maximum value of a string of length i + n ending
        with the jth n-gram.
    graph_weights : array, shape = [n_partitions, len(alphabet)**n]
        Weight of each n-gram.
    y_length : int
        Length of the string to predict.
    gs_kernel : GenericStringKernel
        Generic String Kernel with position and n-gram penalties.

    Returns
    -------
    node_creator : NodeCreator
        Node creator for the branch and bound search instantiated with the generic string bounds
    """
    n_gram_to_index = get_n_gram_to_index(alphabet, n)

# Path: preimage/utils/position.py
# def compute_position_weights(position_index, max_position, sigma_position):
#     position_penalties = numpy.array([(position_index - j) ** 2 for j in range(max_position)], dtype=numpy.float)
#     position_penalties /= -2. * (sigma_position ** 2)
#     return numpy.exp(position_penalties)
# 
# Path: preimage/utils/alphabet.py
# def get_n_gram_to_index(alphabet, n):
#     n_grams = get_n_grams(alphabet, n)
#     indexes = numpy.arange(len(n_grams))
#     n_gram_to_index = dict(zip(n_grams, indexes))
#     return n_gram_to_index
# 
# def get_n_grams(alphabet, n):
#     n = int(n)
#     if n <= 0:
#         raise InvalidNGramLengthError(n)
#     n_grams = [''.join(n_gram) for n_gram in product(alphabet, repeat=n)]
#     return n_grams


# Path: preimage/inference/bound_factory.py
import numpy
from preimage.inference.bound_calculator import OCRMinBoundCalculator, MaxBoundCalculator, PeptideMinBoundCalculator
from preimage.inference.node_creator import NodeCreator
from preimage.utils.position import compute_position_weights
from preimage.utils.alphabet import get_n_gram_to_index, get_n_grams



def get_gs_similarity_node_creator(alphabet, n, graph, graph_weights, y_length, gs_kernel):
    """Create the bounds and the node creator for the branch and bound search of the generic string kernel.

    Takes in account the position and the n-gram penalties when comparing strings (sigma_p and sigma_c in the
    gs kernel).

    Parameters
    ----------
    alphabet : list
        List of letters.
    n : int
        N-gram length.
    graph : array, shape = [n_partitions, len(alphabet)**n]
        Array representation of the graph. graph[i, j] represents the maximum value of a string of length i + n ending
        with the jth n-gram.
    graph_weights : array, shape = [n_partitions, len(alphabet)**n]
        Weight of each n-gram.
    y_length : int
        Length of the string to predict.
    gs_kernel : GenericStringKernel
        Generic String Kernel with position and n-gram penalties.

    Returns
    -------
    node_creator : NodeCreator
        Node creator for the branch and bound search instantiated with the generic string bounds
    """
    n_gram_to_index = get_n_gram_to_index(alphabet, n)

    letter_to_index = get_n_gram_to_index(alphabet, 1)