<reponame>pedronarloch/jMetalPy_phD
import copy
from abc import ABC, abstractmethod
from typing import TypeVar, Generic, List

from jmetal.core.problem import Problem
from jmetal.problem.singleobjective.protein_structure_prediction import ProteinStructurePrediction
from jmetal.core.solution import Solution
from jmetal.util.APL import hists as apl
import numpy as np

R = TypeVar('R')

"""
.. module:: generator
   :platform: Unix, Windows
   :synopsis: Population generators implementation.

.. moduleauthor:: <NAME> <<EMAIL>>
"""


class Generator(Generic[R], ABC):

    @abstractmethod
    def new(self, problem: Problem = None) -> R:
        pass

    @abstractmethod
    def set_problem(self, problem: Problem = None):
        pass


class RandomGenerator(Generator):
    problem = None

    def new(self, problem: Problem = None):
        if problem is not None:
            self.problem = problem

        return self.problem.create_solution()

    def set_problem(self, problem: Problem = None):
        self.problem = problem


class InjectorGenerator(Generator):
    problem = None

    def __init__(self, solutions: List[Solution]):
        super(InjectorGenerator, self).__init__()
        self.population = []

        for solution in solutions:
            self.population.append(copy.deepcopy(solution))

    def new(self, problem: Problem = None):
        if len(self.population) > 0:
            # If we have more solutions to inject, return one from the list
            return self.population.pop()
        else:
            # Otherwise generate a new solution
            solution = problem.create_solution()

        return solution

    def set_problem(self, problem: Problem = None):
        self.problem = problem


class ArchiveInjector(Generator):

    def __init__(self, file_path: str = None, problem: Problem = None):
        self.file_path = file_path
        self.problem = problem
        self.list_of_solutions = None
        self.create_list_of_solutions()

    def create_list_of_solutions(self):
        self.list_of_solutions = []
        list_of_individuals = np.loadtxt(self.file_path, delimiter=',', dtype=float)

        for variables in list_of_individuals:
            sol = self.problem.create_solution()
            sol.variables = variables
            self.list_of_solutions.append(sol)

    def new(self, problem: Problem = None) -> Solution:
        if len(self.list_of_solutions) > 0:
            solution = self.list_of_solutions.pop()
        else:
            solution = self.problem.create_solution()

        return solution

    def set_problem(self, problem: Problem = None):
        self.problem = problem


class APLGenerator(Generator):
    problem = None

    def __init__(self, protein, fasta, secondary_structure, energy_type: str = 'score3'):
        self.apl_hist = apl.HistogramFiles(protein, fasta, secondary_structure, 3)
        self.energy_type = energy_type

    def new(self, problem: ProteinStructurePrediction = None):
        solution = self.problem.create_solution()

        generated_angles = self.apl_hist.create_protein()

        aux = []

        if self.energy_type == "centroid":
            for i in range(0, len(generated_angles)):
                aux = aux + generated_angles[i][:2]
        elif self.energy_type == "ref2015":
            for i in range(0, len(generated_angles)):
                aux = aux + generated_angles[i][:2]
                for j in range(3, len(generated_angles[i])):
                    if generated_angles[i][j] == 999.9:
                        break

                    aux.append(generated_angles[i][j])

        solution.variables = aux

        return solution

    def set_problem(self, problem: Problem = None):
        self.problem = problem
import copy
from abc import ABC, abstractmethod
from typing import TypeVar, Generic, List

from jmetal.core.problem import Problem
from jmetal.problem.singleobjective.protein_structure_prediction import ProteinStructurePrediction
from jmetal.core.solution import Solution
from jmetal.util.APL import hists as apl
import numpy as np

R = TypeVar('R')

"""
.. module:: generator
   :platform: Unix, Windows
   :synopsis: Population generators implementation.

.. moduleauthor:: <NAME> <<EMAIL>>
"""


class Generator(Generic[R], ABC):

    @abstractmethod
    def new(self, problem: Problem = None) -> R:
        pass

    @abstractmethod
    def set_problem(self, problem: Problem = None):
        pass


class RandomGenerator(Generator):
    problem = None

    def new(self, problem: Problem = None):
        if problem is not None:
            self.problem = problem

        return self.problem.create_solution()

    def set_problem(self, problem: Problem = None):
        self.problem = problem


class InjectorGenerator(Generator):
    problem = None

    def __init__(self, solutions: List[Solution]):
        super(InjectorGenerator, self).__init__()
        self.population = []

        for solution in solutions:
            self.population.append(copy.deepcopy(solution))

    def new(self, problem: Problem = None):
        if len(self.population) > 0:
            # If we have more solutions to inject, return one from the list
            return self.population.pop()
        else:
            # Otherwise generate a new solution
            solution = problem.create_solution()

        return solution

    def set_problem(self, problem: Problem = None):
        self.problem = problem


class ArchiveInjector(Generator):

    def __init__(self, file_path: str = None, problem: Problem = None):
        self.file_path = file_path
        self.problem = problem
        self.list_of_solutions = None
        self.create_list_of_solutions()

    def create_list_of_solutions(self):
        self.list_of_solutions = []
        list_of_individuals = np.loadtxt(self.file_path, delimiter=',', dtype=float)

        for variables in list_of_individuals:
            sol = self.problem.create_solution()
            sol.variables = variables
            self.list_of_solutions.append(sol)

    def new(self, problem: Problem = None) -> Solution:
        if len(self.list_of_solutions) > 0:
            solution = self.list_of_solutions.pop()
        else:
            solution = self.problem.create_solution()

        return solution

    def set_problem(self, problem: Problem = None):
        self.problem = problem


class APLGenerator(Generator):
    problem = None

    def __init__(self, protein, fasta, secondary_structure, energy_type: str = 'score3'):
        self.apl_hist = apl.HistogramFiles(protein, fasta, secondary_structure, 3)
        self.energy_type = energy_type

    def new(self, problem: ProteinStructurePrediction = None):
        solution = self.problem.create_solution()

        generated_angles = self.apl_hist.create_protein()

        aux = []

        if self.energy_type == "centroid":
            for i in range(0, len(generated_angles)):
                aux = aux + generated_angles[i][:2]
        elif self.energy_type == "ref2015":
            for i in range(0, len(generated_angles)):
                aux = aux + generated_angles[i][:2]
                for j in range(3, len(generated_angles[i])):
                    if generated_angles[i][j] == 999.9:
                        break

                    aux.append(generated_angles[i][j])

        solution.variables = aux

        return solution

    def set_problem(self, problem: Problem = None):
        self.problem = problem
.. module:: generator    :platform: Unix, Windows    :synopsis: Population generators implementation.  .. moduleauthor:: <NAME> <<EMAIL>> # If we have more solutions to inject, return one from the list # Otherwise generate a new solution