UNPKG

vrp-tabu-search

Version:

Tabu Search Algorithm for Vehicle Routing Problem

151 lines (121 loc) 5.07 kB
var util = require('util'); var assert = require('assert'); var defineClass = require('simple-cls').defineClass; var OSolution = require('./OSolution.js'); var OProblem = require('./OProblem.js'); var SLS_MAX_LS_STEPS = 1000; /** Base Class for a Stochastic Local Search Algorithm **/ var SLS = defineClass({ name : "SLS", /** initiliaze an algorithm with its targer problem instance configuration settings - plateu_move : true to allow local search to move into a solution having the same quality as the previous one。 default true - terminate_ls_steps : search step threshold for stoping the ls - terminate_fitness : fitness threshhold for stopping the ls **/ construct : function(problem, config){ this.problem = problem; this.config = config; //config if(config && config.plateu_move != undefined) this.plateu_move = config.plateu_move; if(config && config.terminate_ls_steps != undefined) this.terminate_ls_steps = config.terminate_ls_steps; if(config && config.terminate_fitness != undefined) this.terminate_fitness = config.terminate_fitness; }, statics : { SOLUTION_QUALITY_MIN_DIFFERENCE : 0.000006 }, variables : { problem : null, ///the underlying problem instance config : null, //algorithm configuration //search state init_sol : null, //initial starting solution cur_sol : null, //current solution during the search process best_sol : null, //best found solution so far cur_step : 0, //current local search steps lo_trap : false, //flag whether current solution is trapped in local optima //configuration options plateu_move : true, //true to allow local search to move into a solution having the same quality as the previous one。 default true terminate_ls_steps : SLS_MAX_LS_STEPS , //search will terminate if this steps is reached terminate_fitness : null //when present, iia will stop if current solution is found equals or better than this valueOf() }, methods : { /** algorithm initialization default implementation initialize with a random solution - reset all internal state to be ready for another independent run subclass can override it to provide alternative initalization scheme **/ init: function (sol) { //console.log(sol); this.init_sol = this.init_solution(sol); //console.log('init_sol'); //console.log(this.init_sol); this.cur_sol = this.init_sol; this.best_sol = this.init_sol; this.lo_trap = false; this.cur_step = 0; }, /** one independent run of SLS @param op - an operator, when given, will be invoked after every single step function (stepno) - stepno is [0,n] - where 0 indicates initial step **/ run: function (sol, op) { assert.ok(!op || typeof(op) == 'function'); this.init(sol); if (op) op(0); while (true) { if (this.terminate()) break; this.step(this.cur_step); this.cur_step += 1; if (this._better(this.cur_sol, this.best_sol)) this.best_sol = this.cur_sol; // best known solution if (op) op(this.cur_step); } }, /** termination criteria returns true if algs should terminate, otherwise false - subclass can override it to add more termination conditions **/ terminate : function(){ var threshFitSol = new OSolution(null,this.terminate_fitness); if(this.lo_trap) return true; //if previous step hit local optima if(this.cur_step >= this.terminate_ls_steps) return true; //reaching user-specified max steps if(this.terminate_fitness && (this._equal(this.best_sol, threshFitSol) || this._better(this.best_sol, threshFitSol))) return true; //if use threshold fitness and we found better, break if(this.cur_step > SLS_MAX_LS_STEPS) return true; //reaching system-defined max steps (so it won't just run forever!) return false; }, //default gives a random solution //subclass to provide custom initial solution init_solution: function (sol) { //console.log(this.problem); return this.problem.initSolution(sol); }, /** a single local search step @param n - gives the step count (starting with 1 as init is the 0 step) **/ step : function(n){assert.ok("not implemented");}, /** define the transient operator / neighborhood structure returns the set of all neighbor candidates Time Complexity O(K) where K is the branching factor from a single solution node in the app's search landscape **/ neighbors : function(sol){assert.ok("not implemented");}, //given a solution, returns a random neighbors of it neighbor : function(sol){assert.ok("not implemented");}, // --- utility functions //given two problem solution, determine which solution is better //return true is s1 is better than s2 _better : function(s1,s2){ return this.problem.minimization ? (s1.fitness < s2.fitness) : (s1.fitness > s2.fitness); }, //given two problem solution ,determine if they have equal quality / fitness _equal : function(s1,s2){ return Math.abs(s1.fitness - s2.fitness) <= SLS.SOLUTION_QUALITY_MIN_DIFFERENCE; } } }); module.exports = exports = SLS;