maths.ts
Version:
Math utilities library for TypeScript, JavaScript and Node.js
88 lines (81 loc) • 2.74 kB
text/typescript
/**
* @author Hector J. Vasquez <ipi.vasquez@gmail.com>
*
* @licence
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _debug from 'debug';
import {NPProblem} from './';
const debug = _debug('mh::ts');
/**
*
* @param problem The problem which must have a solution generator, a
* calculator for the solution and a neighbor generator for each solution.
* @param nNeighbors The number of neighbors for the solution generated each
* cycle.
* @param kDiffer The percentage change of each neighbor from the solution.
* @param tlSize The taboo list size.
* @param iterations The number of iterations executing the algorithm.
* @returns The solution found by this algorithm.
*/
export function tabooSearch<T>(problem: NPProblem<T>,
nNeighbors: number = 5,
kDiffer: number = 2,
tlSize: number = 30,
iterations: number = 100): T {
// Generates an initial solution
const sol = problem.generateSolution();
const tabooList: T[] = [];
let bestS = sol;
debug('Initial sol: ' + bestS);
let bestVal = problem.solutionValue(bestS);
for (let i = 0; i < iterations; i++) {
const neighbors = problem.generateNeighbors(sol, kDiffer, nNeighbors);
const candidates: T[] = [];
neighbors.forEach(n => {
debug('%s=%d', '' + n, problem.solutionValue(n));
if (!isIn(n, tabooList)) {
candidates.push(n);
}
});
let bestC: T = candidates[0];
let bestCVal = 0;
candidates.forEach(c => {
const cVal = problem.solutionValue(c);
if (cVal > bestCVal) {
bestCVal = cVal;
bestC = c;
}
});
debug('Picked: %s=%d', '' + bestC, bestCVal);
if (bestCVal > bestVal) {
debug('Solution updated to ' + bestC);
bestS = bestC;
bestVal = bestCVal;
tabooList.unshift(bestC);
if (tabooList.length >= tlSize) {
tabooList.pop();
}
}
}
debug(tabooList);
return bestS;
function isIn(e: T, array: T[]): boolean {
for (let i = 0; i < array.length; i++) {
if (problem.compareSolutions(array[i], e)) {
return true;
}
}
return false;
}
}