From 4b5194811817d7a7ab7c0fab65d9a420914baf06 Mon Sep 17 00:00:00 2001 From: verel Date: Wed, 14 Dec 2011 22:02:54 +0000 Subject: [PATCH] A lot a small change to improve the things, and new moBitsWithReplNeighborhhod git-svn-id: svn://scm.gforge.inria.fr/svnroot/paradiseo@2564 331e1502-861f-0410-8da2-ba01fb791d7f --- trunk/paradiseo-mo/src/algo/moFirstImprHC.h | 8 + trunk/paradiseo-mo/src/algo/moLocalSearch.h | 4 - .../src/eval/moUBQPdoubleIncrEvaluation.h | 57 +---- .../paradiseo-mo/src/explorer/moVNSexplorer.h | 28 ++- trunk/paradiseo-mo/src/mo.h | 2 + .../problems/bitString/moBitsNeighborhood.h | 134 +++--------- .../bitString/moBitsWithReplNeighborhood.h | 199 ++++++++++++++++++ .../bitString/moBitsWithoutReplNeighborhood.h | 97 +++++++-- .../src/problems/eval/moUBQPBitsIncrEval.h | 124 +++++++++++ 9 files changed, 474 insertions(+), 179 deletions(-) create mode 100644 trunk/paradiseo-mo/src/problems/bitString/moBitsWithReplNeighborhood.h create mode 100644 trunk/paradiseo-mo/src/problems/eval/moUBQPBitsIncrEval.h diff --git a/trunk/paradiseo-mo/src/algo/moFirstImprHC.h b/trunk/paradiseo-mo/src/algo/moFirstImprHC.h index 197fc3cae..67030da6e 100644 --- a/trunk/paradiseo-mo/src/algo/moFirstImprHC.h +++ b/trunk/paradiseo-mo/src/algo/moFirstImprHC.h @@ -90,6 +90,14 @@ public: explorer(_neighborhood, _eval, _compN, _compSN) {} + /** + * Return the class id. + * @return the class name as a std::string + */ + virtual std::string className() const { + return "moFirstImprHV"; + } + private: // always true continuator moTrueContinuator trueCont; diff --git a/trunk/paradiseo-mo/src/algo/moLocalSearch.h b/trunk/paradiseo-mo/src/algo/moLocalSearch.h index 6417af30f..bf77a8f3f 100644 --- a/trunk/paradiseo-mo/src/algo/moLocalSearch.h +++ b/trunk/paradiseo-mo/src/algo/moLocalSearch.h @@ -78,8 +78,6 @@ public: // initialization of the external continuator (for example the time, or the number of generations) cont->init(_solution); - std::cout << _solution.fitness() << std::endl; - bool b; do { // explore the neighborhood of the solution @@ -91,8 +89,6 @@ public: } else searchExplorer.moveApplied(false); - std::cout << _solution.fitness() << std::endl; - // update the parameter of the search (for ex. Temperature of the SA) searchExplorer.updateParam(_solution); diff --git a/trunk/paradiseo-mo/src/eval/moUBQPdoubleIncrEvaluation.h b/trunk/paradiseo-mo/src/eval/moUBQPdoubleIncrEvaluation.h index 52a54b268..5c3dcc484 100644 --- a/trunk/paradiseo-mo/src/eval/moUBQPdoubleIncrEvaluation.h +++ b/trunk/paradiseo-mo/src/eval/moUBQPdoubleIncrEvaluation.h @@ -104,11 +104,12 @@ public: } } else { - if (searchExplorer->moveApplied()) { // compute the new fitness only when the solution has moved - // the currentNeighbor is the previous neighbor + if (searchExplorer->moveApplied()) { + // compute the new fitness only when the solution has moved + // the selectedNeighbor is the neighbor which is selected in the neighborhood // the movement is made on this neighbor // we suppose that the neighborhood is bit string neighborhood (indexed neighbor) - unsigned iMove = searchExplorer->getCurrentNeighbor().index(); + unsigned iMove = searchExplorer->getSelectedNeighbor().index(); for(unsigned i = 0; i < n; i++) { if (i == iMove) @@ -149,56 +150,6 @@ public: } private: - /** - * compute the delta of fitness in linear time (incremental evaluation) - * - * @param i the neighbor to consider - */ - /* - void fullDelta(unsigned int i) { - unsigned int j; - - int d = Q[i][i]; - - for(j = 0; j < i; j++) - if (current[j]) - d += Q[i][j]; - - for(j = i+1; j < n; j++) - if (current[j]) - d += Q[j][i]; - - if (current[i]) - d = - d; - - delta[i] = d; - } -*/ - - /** - * compute the delta of delta in constant time (3 tests and 1 operation) - * - * @param i the neighbor to consider - */ - /* - void updateDelta(unsigned int i) { - if (i == iMove) - delta[i] = - delta[i] ; - else { - if (current[i] != current[iMove]) - if (i < iMove) - delta[i] += Q[iMove][i]; - else - delta[i] += Q[i][iMove]; - else - if (i < iMove) - delta[i] -= Q[iMove][i]; - else - delta[i] -= Q[i][iMove]; - } - } - */ - // number of variables int n; diff --git a/trunk/paradiseo-mo/src/explorer/moVNSexplorer.h b/trunk/paradiseo-mo/src/explorer/moVNSexplorer.h index 5eeaddf6b..3c9c2ef27 100644 --- a/trunk/paradiseo-mo/src/explorer/moVNSexplorer.h +++ b/trunk/paradiseo-mo/src/explorer/moVNSexplorer.h @@ -58,7 +58,7 @@ public: */ moVNSexplorer(moVariableNeighborhoodSelection & _selection, moAcceptanceCriterion& _acceptCrit): - moNeighborhoodExplorer(), selection(_selection), acceptCrit(_acceptCrit), stop(false) + moNeighborhoodExplorer(), selection(_selection), acceptCrit(_acceptCrit), stop(false), first(true) {} /** @@ -72,7 +72,12 @@ public: * @param _solution the current solution */ virtual void initParam(EOT& _solution) { + // the best solution found + bestSoFar = _solution; + // initialization of the LS selection.init(_solution); + // for the first ls, the solution will be improved, so the next ls must be applied + first = true; } /** @@ -80,7 +85,8 @@ public: * @param _solution the current solution */ virtual void updateParam(EOT & _solution) { - if ((*this).moveApplied()) { + if (!first && (*this).moveApplied()) { + first = false; selection.init(_solution); } else if (selection.cont(currentSol)) { @@ -90,9 +96,11 @@ public: } /** - * terminate: NOTHING TO DO + * terminate: return the best solution found */ - virtual void terminate(EOT & _solution) {}; + virtual void terminate(EOT & _solution) { + _solution = bestSoFar; + } /** * Explore the neighborhood of a solution by the "neighborhood" search heuristics @@ -105,6 +113,10 @@ public: currentSol = _solution; shake(currentSol); ls(currentSol); + + // update the best solution found + if (bestSoFar.fitness() < currentSol.fitness()) + bestSoFar = currentSol; } /** @@ -142,10 +154,18 @@ public: } private: + /** the set of LS and shake operators to applied */ moVariableNeighborhoodSelection& selection; + /** Acceptance criterium between two LS */ moAcceptanceCriterion& acceptCrit; + /** stopping criterium flag */ bool stop; + /** the current solution */ EOT currentSol; + /** Best solution found during the search */ + EOT bestSoFar; + /** first LS flag */ + bool first; }; diff --git a/trunk/paradiseo-mo/src/mo.h b/trunk/paradiseo-mo/src/mo.h index 20d841218..3e272a640 100755 --- a/trunk/paradiseo-mo/src/mo.h +++ b/trunk/paradiseo-mo/src/mo.h @@ -60,6 +60,7 @@ #include #include #include +#include #include #include @@ -177,6 +178,7 @@ #include #include #include +#include // #include // #include diff --git a/trunk/paradiseo-mo/src/problems/bitString/moBitsNeighborhood.h b/trunk/paradiseo-mo/src/problems/bitString/moBitsNeighborhood.h index b50c8472e..5bfb2576d 100644 --- a/trunk/paradiseo-mo/src/problems/bitString/moBitsNeighborhood.h +++ b/trunk/paradiseo-mo/src/problems/bitString/moBitsNeighborhood.h @@ -58,99 +58,50 @@ public: * Constructor * @param _length bit string length * @param _nBits maximum number of bits to flip (radius of the neighborhood) + * @param _exactDistance when true, only neighbor with exactly k bits flip are considered, other neighbor <= Hamming distance k */ - moBitsNeighborhood(unsigned _length, unsigned _nBits): moNeighborhood(), length(_length), nBits(_nBits) { - int j; - bool last; - - neighborhoodSize = 0; - - for(int d = 1; d <= nBits; d++) { - vector bits(d); - - // the first one for this Hamming distance - for(unsigned i = 0; i < d; i++) - bits[i] = i; - - neighborsVec.push_back(bits); - - // the others ones - last = false; - - while(!last) { - j = d - 1; - - if (bits[j] < length - 1) { - bits[j]++; - neighborsVec.push_back(bits); - } else { - j--; - - while ( (j >= 0) && (bits[j] + 1 == bits[j+1]) ) - j--; - - if (j < 0) { - last = true; - } else { - bits[j]++; - - for(unsigned i = j+1; i < d; i++) - bits[i] = bits[i-1] + 1; - - neighborsVec.push_back(bits); - } - } - - } + moBitsNeighborhood(unsigned _length, unsigned _nBits, bool _exactDistance = false): moNeighborhood(), length(_length), nBits(_nBits) { + // neighborhood size : + // for distance == nBits : length \choose nBits = length! / ( (length - nBits)! * nBits!) + // for distance <= nBits : sum of previous distances + if (_exactDistance) { + neighborhoodSize = numberOfNeighbors(nBits); + } else { + neighborhoodSize = 0; + for(int d = 1; d <= nBits; d++) + neighborhoodSize += numberOfNeighbors(d); } - neighborhoodSize = neighborsVec.size(); + } + + /** + * Number fo neighbors at Hamming distance d + * + * @param d Hamming distance + */ + unsigned int numberOfNeighbors(unsigned d) { + unsigned int fact_nBits = 1; + + for(unsigned k = 1; k <= d; k++) + fact_nBits *= k; + + unsigned int fact_length = 1; + + for(unsigned k = length; k > length - d; k--) + fact_length *= k; + + return fact_length / fact_nBits; } /** * Test if it exist a neighbor * @param _solution the solution to explore - * @return true if the neighborhood was not empty: the population size is at least 1 + * @return true if the neighborhood was not empty (bit string larger than 0) */ virtual bool hasNeighbor(EOT& _solution) { return _solution.size() > 0; } - /** - * Initialization of the neighborhood: - * apply several bit flips on the solution - * @param _solution the solution to explore - * @param _neighbor the first neighbor - */ - virtual void init(EOT & _solution, Neighbor & _neighbor) { - key = 0; - - _neighbor.bits.resize(nBits); - - setNeighbor(0, _neighbor); - } - - /** - * Give the next neighbor - * apply several bit flips on the solution - * @param _solution the solution to explore (population of solutions) - * @param _neighbor the next neighbor which in order of distance - */ - virtual void next(EOT & _solution, Neighbor & _neighbor) { - key++; - - setNeighbor(key, _neighbor); - } - - /** - * Test if all neighbors are explored or not,if false, there is no neighbor left to explore - * @param _solution the solution to explore - * @return true if there is again a neighbor to explore: population size larger or equals than 1 - */ - virtual bool cont(EOT & _solution) { - return key < neighborhoodSize - 1; - } - /** * Return the class Name * @return the class name as a std::string @@ -159,10 +110,6 @@ public: return "moBitsNeighborhood"; } - unsigned int index() { - return key; - } - protected: // length of the bit strings unsigned int length; @@ -173,25 +120,6 @@ protected: // size of the neighborhood unsigned int neighborhoodSize; - // list of neighbors - vector< vector > neighborsVec; - - // key of the neighbor which is currently explored - unsigned int key; - - - /** - * Set the neighbor to the correct neighbor - * @param _key index in neighborVec of the neighbor to set - * @param _neighbor neighbor to set - */ - virtual void setNeighbor(unsigned _key, Neighbor & _neighbor) { - _neighbor.nBits = neighborsVec[_key].size(); - - for(unsigned i = 0; i < _neighbor.nBits; i++) - _neighbor.bits[i] = neighborsVec[_key][i]; - } - }; #endif diff --git a/trunk/paradiseo-mo/src/problems/bitString/moBitsWithReplNeighborhood.h b/trunk/paradiseo-mo/src/problems/bitString/moBitsWithReplNeighborhood.h new file mode 100644 index 000000000..8c833f1a2 --- /dev/null +++ b/trunk/paradiseo-mo/src/problems/bitString/moBitsWithReplNeighborhood.h @@ -0,0 +1,199 @@ +/* + + Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 + + Sebastien Verel, Arnaud Liefooghe, Jeremie Humeau + + This software is governed by the CeCILL license under French law and + abiding by the rules of distribution of free software. You can use, + modify and/ or redistribute the software under the terms of the CeCILL + license as circulated by CEA, CNRS and INRIA at the following URL + "http://www.cecill.info". + + As a counterpart to the access to the source code and rights to copy, + modify and redistribute granted by the license, users are provided only + with a limited warranty and the software's author, the holder of the + economic rights, and the successive licensors have only limited liability. + + In this respect, the user's attention is drawn to the risks associated + with loading, using, modifying and/or developing or reproducing the + software by the user in light of its specific status of free software, + that may mean that it is complicated to manipulate, and that also + therefore means that it is reserved for developers and experienced + professionals having in-depth computer knowledge. Users are therefore + encouraged to load and test the software's suitability as regards their + requirements in conditions enabling the security of their systems and/or + data to be ensured and, more generally, to use and operate it in the + same conditions as regards security. + The fact that you are presently reading this means that you have had + knowledge of the CeCILL license and that you accept its terms. + + ParadisEO WebSite : http://paradiseo.gforge.inria.fr + Contact: paradiseo-help@lists.gforge.inria.fr +*/ + +#ifndef _moBitsWithReplNeighborhood_h +#define _moBitsWithReplNeighborhood_h + +#include +#include +#include +#include + +/** + * A neighborhood for bit string solutions + * where several bits could be flipped + * under a given Hamming distance + * + * The neighborhood is explored in a random order + * Each neighbors is visited once time + * and the number of visited neighbors is a parameter + */ +template< class Neighbor > +class moBitsWithReplNeighborhood : public moBitsNeighborhood +{ + using moBitsNeighborhood::neighborhoodSize; + using moBitsNeighborhood::length; + using moBitsNeighborhood::nBits; + using moBitsNeighborhood::numberOfNeighbors; + +public: + + /** + * Define type of a solution corresponding to Neighbor + */ + typedef typename Neighbor::EOT EOT; + + /** + * Constructor + * + * @param _length bit string length + * @param _nBits maximum number of bits to flip (radius of the neighborhood) + * @param _sampleSize number of neighbor to sample in the neighborhood, if 0 all the neighborhood is sampled + * @param _exactDistance when true, only neighbor with exactly k bits flip are considered, other neighbor <= Hamming distance k + */ + moBitsWithReplNeighborhood(unsigned _length, unsigned _nBits, unsigned _sampleSize, bool _exactDistance = false): moBitsNeighborhood(_length, _nBits, _exactDistance), sampleSize(_sampleSize), exactDistance(_exactDistance) { + if (sampleSize > neighborhoodSize || sampleSize == 0) + sampleSize = neighborhoodSize; + + indexVector.resize(length); + + for(unsigned int i = 0; i < length; i++) + indexVector[i] = i; + + if (!exactDistance) { + nSize.resize(nBits); + nSize[0] = numberOfNeighbors(1); + for(unsigned d = 2; d <= nBits; d++) + nSize[d - 1] = nSize[d - 2] + numberOfNeighbors(d); + } + + nNeighbors = 0; + } + + /** + * one random neighbor at Hamming distance _n + * + * @param _solution the solution to explore + * @param _neighbor the first neighbor + * @param _n Hamming distance of the neighbor + */ + virtual void randomNeighbor(EOT & _solution, Neighbor & _neighbor, unsigned _n) { + _neighbor.bits.resize(_n); + _neighbor.nBits = _n; + + unsigned i; + unsigned b; + unsigned tmp; + + for(unsigned k = 0; k < _n; k++) { + i = rng.random(length - k); + b = indexVector[i]; + + _neighbor.bits[k] = b; + + indexVector[i] = indexVector[length - k - 1]; + indexVector[length - k - 1] = b; + } + } + + /** + * one random neighbor at maximal Hamming distance _n + * + * @param _solution the solution to explore + * @param _neighbor the first neighbor + */ + virtual void randomNeighbor(EOT & _solution, Neighbor & _neighbor) { + if (exactDistance) + randomNeighbor(_solution, _neighbor, nBits); + else { + // equiprobability between neighbors at maximal Hamming distance nBits + unsigned n = rng.random(neighborhoodSize); + + unsigned d = 1; + while (n < nSize[d - 1]) d++; + + randomNeighbor(_solution, _neighbor, d); + } + } + + /** + * Initialization of the neighborhood: + * one random neighbor + * + * @param _solution the solution to explore + * @param _neighbor the first neighbor + */ + virtual void init(EOT & _solution, Neighbor & _neighbor) { + randomNeighbor(_solution, _neighbor); + + nNeighbors = 1; + } + + /** + * Give the next neighbor + * apply several bit flips on the solution + * @param _solution the solution to explore (population of solutions) + * @param _neighbor the next neighbor which in order of distance + */ + virtual void next(EOT & _solution, Neighbor & _neighbor) { + randomNeighbor(_solution, _neighbor); + + nNeighbors++; + } + + /** + * Test if all neighbors are explored or not,if false, there is no neighbor left to explore + * @param _solution the solution to explore + * @return true if there is again a neighbor to explore: population size larger or equals than 1 + */ + virtual bool cont(EOT & _solution) { + return nNeighbors < sampleSize ; + } + + /** + * Return the class Name + * @return the class name as a std::string + */ + virtual std::string className() const { + return "moBitsWithReplNeighborhood"; + } + +protected: + // vector of possible bits + std::vector indexVector; + + // maximum number of visited neighbor i.e. number of neighbor to sample in the neighborhood + unsigned int sampleSize; + + // number of visited neighbors + unsigned nNeighbors; + + // when true, only neighbors at Hamming distance nBits + bool exactDistance; + + // the number of neighbors below the given distance + std::vector nSize; +}; + +#endif diff --git a/trunk/paradiseo-mo/src/problems/bitString/moBitsWithoutReplNeighborhood.h b/trunk/paradiseo-mo/src/problems/bitString/moBitsWithoutReplNeighborhood.h index eba60ff99..c07bc451c 100644 --- a/trunk/paradiseo-mo/src/problems/bitString/moBitsWithoutReplNeighborhood.h +++ b/trunk/paradiseo-mo/src/problems/bitString/moBitsWithoutReplNeighborhood.h @@ -45,15 +45,15 @@ * where several bits could be flipped * under a given Hamming distance * - * The neighborhood is explred in a random order - * and the number of neighbors is fixed by a number + * The neighborhood is explored in a random order + * Each neighbors is visited once time + * and the number of visited neighbors is a parameter */ template< class Neighbor > class moBitsWithoutReplNeighborhood : public moBitsNeighborhood { using moBitsNeighborhood::neighborhoodSize; - using moBitsNeighborhood::setNeighbor; - using moBitsNeighborhood::key; + using moBitsNeighborhood::length; using moBitsNeighborhood::nBits; public: @@ -67,9 +67,10 @@ public: * Constructor * @param _length bit string length * @param _nBits maximum number of bits to flip (radius of the neighborhood) - * @param _sampleSize number of neighbor to sample in the neighborhood + * @param _sampleSize number of neighbor to sample in the neighborhood, if 0 all the neighborhood is sampled + * @param _exactDistance when true, only neighbor with exactly k bits flip are considered, other neighbor <= Hamming distance k */ - moBitsWithoutReplNeighborhood(unsigned _length, unsigned _nBits, unsigned _sampleSize): moBitsNeighborhood(_length, _nBits), sampleSize(_sampleSize) { + moBitsWithoutReplNeighborhood(unsigned _length, unsigned _nBits, unsigned _sampleSize, bool _exactDistance = false): moBitsNeighborhood(_length, _nBits, _exactDistance), sampleSize(_sampleSize) { if (sampleSize > neighborhoodSize || sampleSize == 0) sampleSize = neighborhoodSize; @@ -77,17 +78,64 @@ public: for(unsigned int i = 0; i < neighborhoodSize; i++) indexVector[i] = i; + + /* all the neighbors */ + if (neighborhoodSize >= 1000000) { + std::cout << "moBitsNeighborhood::Warning : the neighborhood size is larger than 10^6 : " << neighborhoodSize << std::endl; + } + + int j; + bool last; + + unsigned firstIndex; + if (_exactDistance) + firstIndex = nBits; + else + firstIndex = 1; + + for(int d = firstIndex; d <= nBits; d++) { + vector bits(d); + + // the first one for this Hamming distance + for(unsigned i = 0; i < d; i++) + bits[i] = i; + + neighborsVec.push_back(bits); + + // the others ones + last = false; + + while(!last) { + j = d - 1; + + if (bits[j] < length - 1) { + bits[j]++; + neighborsVec.push_back(bits); + } else { + j--; + + while ( (j >= 0) && (bits[j] + 1 == bits[j+1]) ) + j--; + + if (j < 0) { + last = true; + } else { + bits[j]++; + + for(unsigned i = j+1; i < d; i++) + bits[i] = bits[i-1] + 1; + + neighborsVec.push_back(bits); + } + } + + } + } + + if (neighborhoodSize != neighborsVec.size()) + std::cout << "moBitsNeighborhood::Warning -> error in the neighborhood size computation, please check... : " << neighborhoodSize << " / " << neighborsVec.size() << std::endl; } - /** - * Test if it exist a neighbor - * @param _solution the solution to explore - * @return true if the neighborhood was not empty: the population size is at least 1 - */ - virtual bool hasNeighbor(EOT& _solution) { - return _solution.size() > 0; - } - /** * Initialization of the neighborhood: * apply several bit flips on the solution @@ -157,6 +205,25 @@ protected: // maximum number of visited neighbor i.e. number of neighbor to sample in the neighborhood unsigned int sampleSize; + + // list of neighbors + vector< vector > neighborsVec; + + // key of the neighbor which is currently explored + unsigned int key; + + /** + * Set the neighbor to the correct neighbor + * @param _key index in neighborVec of the neighbor to set + * @param _neighbor neighbor to set + */ + virtual void setNeighbor(unsigned _key, Neighbor & _neighbor) { + _neighbor.nBits = neighborsVec[_key].size(); + + for(unsigned i = 0; i < _neighbor.nBits; i++) + _neighbor.bits[i] = neighborsVec[_key][i]; + } + }; #endif diff --git a/trunk/paradiseo-mo/src/problems/eval/moUBQPBitsIncrEval.h b/trunk/paradiseo-mo/src/problems/eval/moUBQPBitsIncrEval.h new file mode 100644 index 000000000..d6a55c3d7 --- /dev/null +++ b/trunk/paradiseo-mo/src/problems/eval/moUBQPBitsIncrEval.h @@ -0,0 +1,124 @@ +/* + +Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 + +Sebastien Verel, Arnaud Liefooghe, Jeremie Humeau + +This software is governed by the CeCILL license under French law and +abiding by the rules of distribution of free software. You can ue, +modify and/ or redistribute the software under the terms of the CeCILL +license as circulated by CEA, CNRS and INRIA at the following URL +"http://www.cecill.info". + +In this respect, the user's attention is drawn to the risks associated +with loading, using, modifying and/or developing or reproducing the +software by the user in light of its specific status of free software, +that may mean that it is complicated to manipulate, and that also +therefore means that it is reserved for developers and experienced +professionals having in-depth computer knowledge. Users are therefore +encouraged to load and test the software's suitability as regards their +requirements in conditions enabling the security of their systems and/or +data to be ensured and, more generally, to use and operate it in the +same conditions as regards security. +The fact that you are presently reading this means that you have had +knowledge of the CeCILL license and that you accept its terms. + +ParadisEO WebSite : http://paradiseo.gforge.inria.fr +Contact: paradiseo-help@lists.gforge.inria.fr +*/ + +#ifndef _moUBQPBitsIncrEval_H +#define _moUBQPBitsIncrEval_H + +#include +#include + +/** + * Incremental evaluation Function for the UBQPSimple problem + * when several bits are flipped (moBitsNeighbor) + */ +template< class Neighbor > +class moUBQPBitsIncrEval : public moEval +{ +public: + typedef typename Neighbor::EOT EOT; + + /* + * default constructor + * @param _ubqpEval full evaluation of the UBQP problem + */ + moUBQPBitsIncrEval(UbqpEval & _ubqpEval) { + n = _ubqpEval.getNbVar(); + Q = _ubqpEval.getQ(); + } + + /* + * Incremental evaluation of the neighbor for the UBQP problem (complexity O(n * k) when k bits are flipped) + * @param _solution the solution to move (bit string) + * @param _neighbor the neighbor to consider of type moBitsNeighbor (several bits are flipped) + */ + virtual void operator()(EOT & _solution, Neighbor & _neighbor) { + unsigned int b; + unsigned int j; + int d, delta; + + delta = 0; + for(unsigned i = 0; i < _neighbor.nBits; i++) { + b = _neighbor.bits[i]; + d = Q[b][b]; + + for(j = 0; j < b; j++) + if (_solution[j] == 1) + d += Q[b][j]; + + for(j = b+1; j < n; j++) + if (_solution[j] == 1) + d += Q[j][b]; + + if (_solution[b] == 0) + delta += d; + else + delta -= d; + + // move the solution on this bit + _solution[b] = !_solution[b]; + } + + // move back the solution + for(unsigned i = 0; i < _neighbor.nBits; i++) { + b = _neighbor.bits[i]; + _solution[b] = !_solution[b]; + } + + _neighbor.fitness(_solution.fitness() + delta); + } + + /* + * to get the matrix Q + * + * @return matrix Q + */ + int** getQ() { + return Q; + } + + /* + * to get the number of variable (bit string length) + * + * @return bit string length + */ + int getNbVar() { + return n; + } + +private: + // number of variables + int n; + + // matrix Q (supposed to be in lower triangular form) + int ** Q; + +}; + +#endif +