# Path: framework/global_resources.py
# class UI(object):
#     """
#     Once initialized, attributes cannot be modified
#     """
#     def __init__(self, **kwargs):
#         self._inputs = {}
#         for k, v in kwargs.items():
#             self._inputs[k] = v
# 
#     # for python2 compatibility
#     def __nonzero__(self):
#         return bool(self._inputs)
# 
#     # for python3 compatibility
#     def __bool__(self):
#         return bool(self._inputs)
# 
#     def get_inputs(self):
#         return self._inputs
# 
#     def is_attrs_defined(self, *names):
#         for n in names:
#             if n not in self._inputs:
#                 return False
#         return True
# 
#     def set_user_inputs(self, user_inputs):
#         assert isinstance(user_inputs, dict)
#         self._inputs = user_inputs
# 
#     def check_conformity(self, valid_args):
#         for arg in self._inputs:
#             if arg not in valid_args:
#                 return False, arg
#         return True, None
# 
#     def __getattr__(self, name):
#         if name in self._inputs:
#             return self._inputs[name]
#         else:
#             return None
# 
#     def __str__(self):
#         if self._inputs:
#             ui = '['
#             for k, v in self._inputs.items():
#                 ui += "{:s}={!r},".format(k, v)
#             return ui[:-1]+']'
#         else:
#             return '[ ]'
# 
#     def __copy__(self):
#         new_ui = type(self)()
#         new_ui.__dict__.update(self.__dict__)
#         new_ui._inputs = copy.copy(self._inputs)
#         return new_ui
# 
# Path: framework/error_handling.py
# class ExtinctPopulationError(PopulationError): pass
# 
# class PopulationError(Exception): pass


from operator import attrgetter
from framework.tactics_helpers import *
from framework.global_resources import UI
from framework.scenario import *
from framework.error_handling import ExtinctPopulationError, PopulationError
        """ Operates three bit flips on each individual """
        for individual in self._individuals:
            individual.mutate(3)
            print(str(individual) + "mutated !!")

    def _crossover(self):
        """ Compensates the kills through the usage of the tCOMB disruptor """
        random.shuffle(self._individuals)

        current_size = len(self._individuals)

        i = 0
        while len(self._individuals) < self.SIZE and i < int(current_size / 2):
            ind_1 = self._individuals[i].node
            ind_2 = self._individuals[i+1].node.get_clone()


            while True:
                data = self._fmk.get_data([('tCOMB', UI(node=ind_2))], data_orig=Data(ind_1))
                if data is None or data.is_unusable():
                    break
                else:
                    self._individuals.append(DefaultIndividual(self._fmk, data.content))

            i += 2

    def evolve(self):
        """ Describe the evolutionary process """

        if len(self) < 2:

# Path: framework/global_resources.py
# class UI(object):
#     """
#     Once initialized, attributes cannot be modified
#     """
#     def __init__(self, **kwargs):
#         self._inputs = {}
#         for k, v in kwargs.items():
#             self._inputs[k] = v
# 
#     # for python2 compatibility
#     def __nonzero__(self):
#         return bool(self._inputs)
# 
#     # for python3 compatibility
#     def __bool__(self):
#         return bool(self._inputs)
# 
#     def get_inputs(self):
#         return self._inputs
# 
#     def is_attrs_defined(self, *names):
#         for n in names:
#             if n not in self._inputs:
#                 return False
#         return True
# 
#     def set_user_inputs(self, user_inputs):
#         assert isinstance(user_inputs, dict)
#         self._inputs = user_inputs
# 
#     def check_conformity(self, valid_args):
#         for arg in self._inputs:
#             if arg not in valid_args:
#                 return False, arg
#         return True, None
# 
#     def __getattr__(self, name):
#         if name in self._inputs:
#             return self._inputs[name]
#         else:
#             return None
# 
#     def __str__(self):
#         if self._inputs:
#             ui = '['
#             for k, v in self._inputs.items():
#                 ui += "{:s}={!r},".format(k, v)
#             return ui[:-1]+']'
#         else:
#             return '[ ]'
# 
#     def __copy__(self):
#         new_ui = type(self)()
#         new_ui.__dict__.update(self.__dict__)
#         new_ui._inputs = copy.copy(self._inputs)
#         return new_ui
# 
# Path: framework/error_handling.py
# class ExtinctPopulationError(PopulationError): pass
# 
# class PopulationError(Exception): pass


# Path: framework/evolutionary_helpers.py
from operator import attrgetter
from framework.tactics_helpers import *
from framework.global_resources import UI
from framework.scenario import *
from framework.error_handling import ExtinctPopulationError, PopulationError

        """ Operates three bit flips on each individual """
        for individual in self._individuals:
            individual.mutate(3)
            print(str(individual) + "mutated !!")

    def _crossover(self):
        """ Compensates the kills through the usage of the tCOMB disruptor """
        random.shuffle(self._individuals)

        current_size = len(self._individuals)

        i = 0
        while len(self._individuals) < self.SIZE and i < int(current_size / 2):
            ind_1 = self._individuals[i].node
            ind_2 = self._individuals[i+1].node.get_clone()


            while True:
                data = self._fmk.get_data([('tCOMB', UI(node=ind_2))], data_orig=Data(ind_1))
                if data is None or data.is_unusable():
                    break
                else:
                    self._individuals.append(DefaultIndividual(self._fmk, data.content))

            i += 2

    def evolve(self):
        """ Describe the evolutionary process """

        if len(self) < 2:

            raise ExtinctPopulationError()