docs: def geno(self, y, from_bounds=None,
               copy_if_changed=True, copy_always=False,
               repair=None, archive=None):
          """maps the phenotypic input argument into the genotypic space,
          that is, computes essentially the inverse of ``pheno``.
  
          By default a copy is made only to prevent to modify ``y``.
  
          The inverse of the user-defined transformation (if any)
          is only needed if external solutions are injected, it is not
          applied to the initial solution x0.
  
          Details
          =======
          ``geno`` searches first in ``archive`` for the genotype of
          ``y`` and returns the found value, typically unrepaired.
          Otherwise, first ``from_bounds`` is applied, to revert a
          projection into the bound domain (if necessary) and ``pheno``
          is reverted. ``repair`` is applied last, and is usually the
          method ``CMAEvolutionStrategy.repair_genotype`` that limits the
          Mahalanobis norm of ``geno(y) - mean``.
  
          """
          if from_bounds is None:
              from_bounds = lambda x, copy=False: x  # not change, no copy
  
          if archive is not None:
              try:
                  x = archive[y]['geno']
              except (KeyError, TypeError):
                  x = None
              if x is not None:
                  if archive[y]['iteration'] < archive.last_iteration \
                          and repair is not None:
                      x = repair(x, copy_if_changed=copy_always)
                  return x
  
          input_type = type(y)
          x = y
          if copy_always:
              x = array(y, copy=True)
              copy = False
          else:
              copy = copy_if_changed
  
          x = from_bounds(x, copy)
  
          if self.isidentity:
              if repair is not None:
                  x = repair(x, copy)
              return x
  
          if copy:  # could be improved?
              x = array(x, copy=True)
              copy = False
  
          # user-defined transformation
          if self.tf_geno is not None:
              x = array(self.tf_geno(x), copy=False)
          elif self.tf_pheno is not None:
              raise ValueError('t1 of options transformation was not defined but is needed as being the inverse of t0')
  
          # affine-linear transformation: shift and scaling
          if self.typical_x is not 0:
              x -= self.typical_x
          if self.scales is not 1:  # just for efficiency
              x /= self.scales
  
          # kick out fixed_values
          if self.fixed_values is not None:
              # keeping the transformed values does not help much
              # therefore it is omitted
              if 1 < 3:
                  keys = sorted(self.fixed_values.keys())
                  x = array([x[i] for i in xrange(len(x)) if i not in keys],
                            copy=False)
          # repair injected solutions
          if repair is not None:
              x = repair(x, copy)
          if input_type is np.ndarray:
              x = array(x, copy=False)
          return x