Skip to content

Commit

Permalink
Add: numeric crossover started
Browse files Browse the repository at this point in the history
  • Loading branch information
CristianAbrante committed May 13, 2019
1 parent 7ed2827 commit 4f124bc
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 0 deletions.
73 changes: 73 additions & 0 deletions src/lib/crossover/numeric/floating/BaseFloatingCrossover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* @license
* Copyright (c) 2019 Cristian Abrante. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*/

import { Generator } from '../../../generator/utils';
import { NumericRange } from '../../../individual/numeric/base';
import { FloatingIndividual } from '../../../individual/numeric/floating';
import BaseCrossover from '../../base/BaseCrossover';
import { CrossoverParams, IndividualConstructor } from '../../base/Crossover';

export interface BaseFloatingCrossoverParams extends CrossoverParams<FloatingIndividual, number> {
alpha: number;
}

abstract class BaseFloatingCrossover extends BaseCrossover<FloatingIndividual, number, BaseFloatingCrossoverParams> {
private recombinationPoint: number = 0;
public cross(
firstParent: FloatingIndividual,
secondParent: FloatingIndividual,
alpha = 0.5,
engine = Generator.DEFAULT_ENGINE,
): FloatingIndividual[] {
return this.crossWith(firstParent, secondParent, { engine, alpha, individualConstructor: FloatingIndividual });
}

public crossWith(
firstParent: FloatingIndividual,
secondParent: FloatingIndividual,
params: BaseFloatingCrossoverParams,
): FloatingIndividual[] {
this.generateRecombinationPoint(firstParent.length(), params);
this.checkParams(params);
return super.crossWith(firstParent, secondParent, params);
}

protected getGenotypeValues(
firstParent: FloatingIndividual,
secondParent: FloatingIndividual,
params: BaseFloatingCrossoverParams,
index: number,
): { first: number; second: number } {
const recombinationCondition = this.getRecombinationCondition(index);
const firstValue = firstParent.get(index);
const secondValue = secondParent.get(index);
return {
first: recombinationCondition ? firstValue : this.getRecombinationValue(firstValue, secondValue, params),
second: recombinationCondition ? secondValue : this.getRecombinationValue(secondValue, firstValue, params),
};
}

protected abstract getRecombinationCondition(index: number): boolean;

protected getRecombinationValue(
firstParentValue: number,
secondParentValue: number,
params: BaseFloatingCrossoverParams,
): number {
const { alpha } = params;
return alpha * firstParentValue + (1.0 - alpha) * secondParentValue;
}

private checkParams(params: BaseFloatingCrossoverParams) {
if (!Generator.probabilityIsValid(params.alpha)) {
throw new Error(`BaseFloatingCrossover: alpha of ${params.alpha} is not in range [0.0, 1.0]`);
}
}

private generateRecombinationPoint(parentsLength: number, params: BaseFloatingCrossoverParams) {
this.recombinationPoint = Generator.generateInteger(new NumericRange(0, parentsLength - 1), params.engine);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* @license
* Copyright (c) 2019 Cristian Abrante. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*/

import { Generator } from '../../../generator/utils';
import { NumericRange } from '../../../individual/numeric/base';
import { FloatingIndividual } from '../../../individual/numeric/floating';
import BaseCrossover from '../../base/BaseCrossover';
import { CrossoverParams, IndividualConstructor } from '../../base/Crossover';

export interface SimpleArithmeticRecombinationParams extends CrossoverParams<FloatingIndividual, number> {
alpha: number;
}

class SimpleArithmeticRecombination extends BaseCrossover<
FloatingIndividual,
number,
SimpleArithmeticRecombinationParams
> {
private recombinationPoint: number = 0;

public cross(
firstParent: FloatingIndividual,
secondParent: FloatingIndividual,
individualConstructor: IndividualConstructor<FloatingIndividual, number>,
alpha = 0.5,
engine = Generator.DEFAULT_ENGINE,
): FloatingIndividual[] {
return this.crossWith(firstParent, secondParent, {
alpha,
engine,
individualConstructor,
});
}

public crossWith(
firstParent: FloatingIndividual,
secondParent: FloatingIndividual,
params: SimpleArithmeticRecombinationParams,
): FloatingIndividual[] {
this.generateRecombinationPoint(firstParent.length(), params);
return super.crossWith(firstParent, secondParent, params);
}

protected getGenotypeValues(
firstParent: FloatingIndividual,
secondParent: FloatingIndividual,
params: SimpleArithmeticRecombinationParams,
index: number,
): { first: number; second: number } {
const parentSelectionCondition = index < this.recombinationPoint;
const firstValue = firstParent.get(index);
const secondValue = secondParent.get(index);
return {
first: parentSelectionCondition ? firstValue : this.getRecombinedValues(secondValue, firstValue, params),
second: parentSelectionCondition ? secondValue : this.getRecombinedValues(firstValue, secondValue, params),
};
}

private getRecombinedValues(firstValue: number, secondValue: number, params: SimpleArithmeticRecombinationParams) {
return params.alpha * firstValue + (1.0 - params.alpha) * secondValue;
}

private generateRecombinationPoint(parentsLength: number, params: SimpleArithmeticRecombinationParams) {
this.recombinationPoint = Generator.generateInteger(new NumericRange(1, parentsLength - 1), params.engine);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* @license
* Copyright (c) 2019 Cristian Abrante. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*/

import { Generator } from '../../../generator/utils';
import { NumericRange } from '../../../individual/numeric/base';
import { FloatingIndividual } from '../../../individual/numeric/floating';
import BaseCrossover from '../../base/BaseCrossover';
import { CrossoverParams } from '../../base/Crossover';
import { SimpleArithmeticRecombinationParams } from './SimpleArithmeticRecombination';

export interface SingleArithmeticRecombinationParams extends CrossoverParams<FloatingIndividual, number> {
alpha: number;
}

class SingleArithmeticRecombination extends BaseCrossover<
FloatingIndividual,
number,
SingleArithmeticRecombinationParams
> {
private recombinationPoint: number = 0;

public cross(
firstParent: FloatingIndividual,
secondParent: FloatingIndividual,
...args: any[]
): FloatingIndividual[] {
return [];
}

public crossWith(
firstParent: FloatingIndividual,
secondParent: FloatingIndividual,
params: SingleArithmeticRecombinationParams,
): FloatingIndividual[] {
this.generateRecombinationPoint(firstParent.length(), params);
return super.crossWith(firstParent, secondParent, params);
}

protected getGenotypeValues(
firstParent: FloatingIndividual,
secondParent: FloatingIndividual,
params: SingleArithmeticRecombinationParams,
index: number,
): { first: number; second: number } {
const parentSelectionCondition = index === this.recombinationPoint;
const firstValue = firstParent.get(index);
const secondValue = secondParent.get(index);
return {
first: parentSelectionCondition ? firstValue : this.getRecombinedValues(secondValue, firstValue, params),
second: parentSelectionCondition ? secondValue : this.getRecombinedValues(firstValue, secondValue, params),
};
}

private getRecombinedValues(firstValue: number, secondValue: number, params: SimpleArithmeticRecombinationParams) {
return params.alpha * firstValue + (1.0 - params.alpha) * secondValue;
}

private generateRecombinationPoint(parentsLength: number, params: SimpleArithmeticRecombinationParams) {
this.recombinationPoint = Generator.generateInteger(new NumericRange(1, parentsLength - 1), params.engine);
}
}

0 comments on commit 4f124bc

Please sign in to comment.