public void mutate(final Set<AbstractKey> keyPool) {
    // there is a chance we will remove a signal gene from the chromatid

    if (Mutations.mutationEvent(mutability))
      if (this.localSignalGenes.size() > 0)
        this.sequencedGenes.remove(
            this.localSignalGenes.remove(
                Mutations.getRandom().nextInt(this.localSignalGenes.size())));

    // there is a chance we will add a new gene to the chromatid
    if (Mutations.mutationEvent(mutability) && getGenes().size() < max) {
      // generate the new receptorKey used in the new gene
      ReceptorKey newReceptorKey = new ReceptorKey(randomKey(keyPool));

      // mutate new receptorKey before using it
      while (Mutations.mutationEvent(this.mutability))
        newReceptorKey = newReceptorKey.mutate(mutability);

      // create a new gene using the new receptor
      AbstractWaveletGene newGene;
      final SignalKey newSignalKey = new SignalKey(randomKey(keyPool));
      switch (RANDOM.nextInt(3)) {
        case 0:
          final MutableInteger initialDistance = (new MutableInteger(0)).mutate(mutability);
          newGene = new PromoterGene(newReceptorKey, initialDistance.intValue());
          this.promoters.add((PromoterGene) newGene);
          break;
        case 1:
          newGene = new SignalGene(newReceptorKey, newSignalKey);
          this.localSignalGenes.add((SignalGene) newGene);
          break;
        default:
          newGene = new ExternalSignalGene(newReceptorKey, newSignalKey, RANDOM.nextBoolean());
          this.externalSignalGenes.add((ExternalSignalGene) newGene);
      }
      // add the new gene to the sequence. there is an equal chance the
      // gene will be added to the head and tail
      if (RANDOM.nextBoolean()) this.sequencedGenes.add(0, newGene);
      else this.sequencedGenes.add(newGene);
    }

    // mutate each gene (the gene itself will handle if it actually mutates)
    for (AbstractWaveletGene currentGene : this.sequencedGenes) currentGene.mutate(keyPool);

    // mutate the mutability factor.
    if (Mutations.mutationEvent(mutability))
      this.mutability = Mutations.mutabilityMutation(this.mutability);
  }