# Path: cameo/strain_design/heuristic/evolutionary/genomes.py
# class MultipleChromosomeGenome(object):
#     def __init__(self, keys=[], *args, **kwargs):
#         super(MultipleChromosomeGenome, self).__init__(*args, **kwargs)
#         self.chromosomes = {k: [] for k in keys}
#         self.keys = keys
# 
#     def __getitem__(self, key):
#         return self.chromosomes[key]
# 
#     def __delitem__(self, key):
#         del self.chromosomes[key]
# 
#     def __setitem__(self, key, value):
#         self.chromosomes[key] = sorted(value)
# 
#     def copy(self):
#         new_genome = MultipleChromosomeGenome(self.keys)
#         for key in self.keys:
#             new_genome[key] = copy(self[key])
#         return new_genome
# 
#     def __repr__(self):
#         return "| ".join(["%s: %s" % (k, list(v)) for k, v in self.chromosomes.items()])


from inspyred.ec.variators import mutator, crossover
from ordered_set import OrderedSet
from cameo.strain_design.heuristic.evolutionary.genomes import MultipleChromosomeGenome
from numpy import float32 as float
import logging
        must contain the representation of each chromosome

    Returns
    -------
    MultipleChromosomeGenome
        A mutated individual
    """
    new_individual = individual.copy()
    max_size = args.get("max_size", 9)
    for key in individual.keys:
        representation = args.get('%s_representation' % key)
        indices = range(len(representation))
        indices = _subtract(indices, individual[key])  # remove indices already present in the individual
        indel_rate = args.get('%s_indel_rate' % key, .1)
        if random.random() < indel_rate:
            if random.random() > 0.5 and len(new_individual[key]) < max_size and len(indices) > 0:
                index = random.sample(indices, 1)[0]
                indices.remove(index)
                new_individual[key].append(index)
            else:
                if len(individual[key]) > 1:
                    new_individual[key] = random.sample(new_individual[key], len(new_individual[key]) - 1)

            assert len(new_individual[key]) <= max_size
            new_individual[key] = sorted(new_individual[key])
    return new_individual


@crossover
def multiple_chromosome_n_point_crossover(random, mom, dad, args):

# Path: cameo/strain_design/heuristic/evolutionary/genomes.py
# class MultipleChromosomeGenome(object):
#     def __init__(self, keys=[], *args, **kwargs):
#         super(MultipleChromosomeGenome, self).__init__(*args, **kwargs)
#         self.chromosomes = {k: [] for k in keys}
#         self.keys = keys
# 
#     def __getitem__(self, key):
#         return self.chromosomes[key]
# 
#     def __delitem__(self, key):
#         del self.chromosomes[key]
# 
#     def __setitem__(self, key, value):
#         self.chromosomes[key] = sorted(value)
# 
#     def copy(self):
#         new_genome = MultipleChromosomeGenome(self.keys)
#         for key in self.keys:
#             new_genome[key] = copy(self[key])
#         return new_genome
# 
#     def __repr__(self):
#         return "| ".join(["%s: %s" % (k, list(v)) for k, v in self.chromosomes.items()])


# Path: cameo/strain_design/heuristic/evolutionary/variators.py
from inspyred.ec.variators import mutator, crossover
from ordered_set import OrderedSet
from cameo.strain_design.heuristic.evolutionary.genomes import MultipleChromosomeGenome
from numpy import float32 as float
import logging

        must contain the representation of each chromosome

    Returns
    -------
    MultipleChromosomeGenome
        A mutated individual
    """
    new_individual = individual.copy()
    max_size = args.get("max_size", 9)
    for key in individual.keys:
        representation = args.get('%s_representation' % key)
        indices = range(len(representation))
        indices = _subtract(indices, individual[key])  # remove indices already present in the individual
        indel_rate = args.get('%s_indel_rate' % key, .1)
        if random.random() < indel_rate:
            if random.random() > 0.5 and len(new_individual[key]) < max_size and len(indices) > 0:
                index = random.sample(indices, 1)[0]
                indices.remove(index)
                new_individual[key].append(index)
            else:
                if len(individual[key]) > 1:
                    new_individual[key] = random.sample(new_individual[key], len(new_individual[key]) - 1)

            assert len(new_individual[key]) <= max_size
            new_individual[key] = sorted(new_individual[key])
    return new_individual


@crossover
def multiple_chromosome_n_point_crossover(random, mom, dad, args):

    children = MultipleChromosomeGenome(keys=mom.keys)