Source

privateer / risky_business / PrivateerCrossovers.py

Full commit
from __future__ import division
import random
import math
from bitwise_utils import MANTISSA_BITS, bitcross

def G1DListCrossoverMean(genome, **args):
    """Ultra-stupid crossover taking the mean of both parents. Not very useful -
    AFAICT it results in pressure to converge to the population mean rather than
    to the solution."""

    sister = None
    brother = None
    gMom = args["mom"]
    gDad = args["dad"]

    sister = gMom.clone()
    brother = gDad.clone()
    sister.resetStats()
    brother.resetStats()

    for i in xrange(len(gMom)):
      sister[i] = brother[i] = (gMom[i]+gDad[i])/2.0
        
    return (sister, brother)

def bitcross(i1, i2, mask):
    """return a new int, containing its chosen from i1 or i2 depending on whther the mask string is 1 or 0"""
    return (i1 & mask) | (i2 & ~mask)
    
def G1DListCrossoverBitwise(genome, **args):
    """bitwise uniform crossover for floats. Warning, potentially breaks range
    constraints."""
    sister = None
    brother = None
    gMom = args["mom"]
    gDad = args["dad"]

    sister = gMom.clone()
    brother = gDad.clone()
    sister.resetStats()
    brother.resetStats()
    
    for i in xrange(len(gMom)):
        mask = random.getrandbits(MANTISSA_BITS) 
        mantissaDad, expDad = math.frexp(gDad[i])
        mantissaMom, expMom = math.frexp(gMom[i])
        baseExp = max(expMom, expDad)
        # import pdb; pdb.set_trace()
        
        mantissaDad = int(mantissaDad*2.**(MANTISSA_BITS-baseExp+expDad))
        mantissaMom = int(mantissaMom*2.**(MANTISSA_BITS-baseExp+expMom))
        
        #Not quite sure why i seem to need the -1 in here, but it makes me
        #distrust the function
        sister[i] = bitcross(mantissaDad, mantissaMom, mask) *\
          2.**(baseExp-MANTISSA_BITS)
        brother[i] = bitcross(mantissaMom, mantissaDad, mask) *\
          2.**(baseExp-MANTISSA_BITS)

        # sister[i] = clip(sister[i],
        #   gMom.getParam('rangemin'),
        #   gMom.getParam('rangemax'))
        # brother[i] = clip(brother[i],
        #   gMom.getParam('rangemin'),
        #   gMom.getParam('rangemax'))
    
    return (sister, brother)


########
def test_mantissa_mathematics():
    """does all my mantisssa maths work? well, if this is stable it does"""
    def rndtrip(f): return int((2<<53)*f)/float(2<<53)
    f=1.0/3.0
    for i in range(100):
       print f.hex()
       f=rndtrip(f)

def clip(f, lbound, ubound):
    return min(max(f, lbound), ubound)