def crossPGA(parentA,parentB,children=2):
    #Creating Child Param
    childParam=param.param()
    #Locking abundance ratios
    if lockTiCr:
        childParam.comp.lockTiCr=True
    if lockScTi:
        childParam.comp.lockScTi=True
    if lockVCr:
        childParam.comp.lockVCr=True
    #Initialising mutation counter
    childParam.mutations=0
    
    selParameters=selElements+['lum','vph']
    selParamLen=len(selParameters)
    
    #Checking crossOverProbability
    crossOverPoint=random.uniform(1,selParamLen-1)
    paramChoice=random.permutation(selParameters)
    #Crossover Selecting from both parents
    for paramName in paramChoice[:crossOverPoint]:
        childParam[paramName]=parentA[paramName]
        
    for paramName in paramChoice[crossOverPoint:]:
        childParam[paramName]=parentB[paramName]
            
    childParam=mutateUniform(childParam)
    childParam.comp.resetOxygen()
    if childParam['O']<0: raise dalekExceptions.geneticException('Crossover: Child has negative oxygen')
    return childParam
def crossArith(parentA,parentB,mutationRate=0.2):
    childParam=param.param()
    rChoice=random.permutation(selElements)
    for element in rChoice:
        childParam[element]=np.mean([parentA[element],parentB[element]])
    if childParam['O']<0: raise Exception('Crossover: Child has negative oxygen')
    if any(np.array(childParam.comp.data.values())<0):
        raise dalekExceptions.geneticException('Negative values: %s'%childParam.comp.data.values())
    childParam['lum']=np.mean([parentA['lum'],parentB['lum']])
    childParam['vph']=np.mean([parentA['vph'],parentB['vph']])
    return childParam
def mutateGauss(childParam,mutateScale=0.01,mutationRate=0.2):
    for element in selElements:
        mutationRate=mutationParams['elements']
        if random.random()<mutationRate:
            childParam[element]*=random.normal(1,mutationParams['elements'])
            childParam.mutations+=1
    if childParam['O']<0: raise dalekExceptions.geneticException('Crossover: Child has negative oxygen')
    if random.random()<mutationParams['lum'][0]:
        childParam['lum']*=random.normal(1,mutationParams['lum'][1])
        childParam.mutations+=1
    if random.random()<mutationParam['vph'][0]:
        childParam['vph']*=random.normal(1,mutationParams['vph'][1])
        childParam.mutations+=1
    return childParam
def crossSingle(parentA,parentB):
    #Creating Child Param
    childParam=param.param()
    #Locking abundance ratios
    if config.GAConfDict['lockTiCr']:
        childParam.comp.lockTiCr=True
    if config.GAConfDict['lockScTi']:
        childParam.comp.lockScTi=True
    if config.GAConfDict['lockVCr']:
        childParam.comp.lockVCr=True
    
    #Initialising mutation counter
    childParam.mutations=0
    
    #selParameters=selElements+['lum','vph']
    
    selParameters=config.GAConfDict['selParameters']
    
    #closedGAParameters = list(set(config.GAConfDict['openGAParametersDefault'])
    #                          - set(config.GAConfDict['openGAParameters']))
    
    closedGAParameters = []
    selParamLen = len(selParameters)
    
    #Checking crossOverProbability
    if random.random()<config.GAConfDict['crossOverProbability']:
        crossOverPoint=random.uniform(1,selParamLen-1)
        paramChoice=random.permutation(selParameters)
        
        #Crossover Selecting from both parents
        for paramName in paramChoice[:crossOverPoint]:
            childParam[paramName]=parentA[paramName]
            
        for paramName in paramChoice[crossOverPoint:]:
            childParam[paramName]=parentB[paramName]
    else:
        #No crossover, selecting parameters from ParentA
        for paramName in selParameters:
            childParam[paramName]=parentA[paramName]
            
    if closedGAParameters != []:
        for paramName in selParameters:
            childParam[paramName] = parentA[paramName]
            
    childParam=mutateUniform(childParam)
    childParam.comp.resetOxygen()
    if childParam['O']<0: raise dalekExceptions.geneticException('Crossover: Child has negative oxygen')
    
    return childParam
def mutateUniform(childParam):
    #HACK WARNING HACK WARNING
    if False:
    #if not lockExperiment:
        for element in selElements:
            #if element=='Ca': continue
            if random.random()<mutationParams['elements'][0]:
                childParam[element]*=random.uniform(1-mutationParams['elements'][1],
                                                    1+mutationParams['elements'][1])
                childParam.mutations+=1
    if childParam['O']<0: raise dalekExceptions.geneticException('Crossover: Child has negative oxygen')
    if random.random()<mutationParams['lum'][0]:
        #childParam['lum']*=random.uniform(1-mutationParams['lum'][1],
        #                                  1+mutationParams['lum'][1])
        childParam['lum']+=random.uniform(-mutationParams['lum'][1],
                                          +mutationParams['lum'][1])
        childParam.mutations+=1
    if random.random()<mutationParams['vph'][0]:
        #childParam['vph']*=random.uniform(1-mutationParams['vph'][1],
        #                                  1+mutationParams['vph'][1])
        childParam['vph']+=random.uniform(-mutationParams['vph'][1],
                                          +mutationParams['vph'][1])
        childParam.mutations+=1
    return childParam