13#ifndef BALANCEDPARTITIONER_HPP_
14#define BALANCEDPARTITIONER_HPP_
37 template<
typename ClassToBeSorted >
46 std::vector< ClassToBeSorted >
const& vectorToBeSorted );
48 std::vector< unsigned int >
const&
64 std::vector< unsigned int >
const&
87 std::list< IndexWithWeight >::const_iterator
94 std::vector< unsigned int >::const_iterator
134 std::vector< unsigned int >& partitionToBeMade );
137 std::vector< unsigned int >& partitionAlreadyMade );
146 template<
typename ClassToBeSorted >
149 double (*weightGetter)( ClassToBeSorted
const& ) ) :
150 sizeOfVectorToSort( 0 ),
151 lowerWeightPartition(),
153 higherWeightPartition(),
155 weightGetter( weightGetter ),
157 positiveWeight( 0.0 ),
159 currentCandidate( NULL ),
160 bestCandidateSoFar( NULL ),
161 currentWeight( 0.0 ),
162 vectorManagingCandidateMemory(),
163 candidatesToBuildOn(),
169 template<
typename ClassToBeSorted >
176 template<
typename ClassToBeSorted >
179 std::vector< ClassToBeSorted >
const& vectorToBeSorted )
183 clearSavedCandidates();
186 sizeOfVectorToSort = vectorToBeSorted.size();
189 for(
unsigned int whichIndex( 0 );
190 sizeOfVectorToSort > whichIndex;
193 positiveWeight = (*weightGetter)( vectorToBeSorted[ whichIndex ] );
194 if( 0.0 > positiveWeight )
196 positiveWeight = -positiveWeight;
198 if( 0.0 < positiveWeight )
200 weightSum += positiveWeight;
206 double const halfTotalWeight( 0.5 * weightSum );
207 if( orderedList.empty() )
216 orderedList.sort( &orderByDouble );
220 if( halfTotalWeight <= orderedList.back().second )
225 higherWeightPartition.push_back( orderedList.back().first );
226 higherWeight = orderedList.back().second;
227 lowerWeight = ( weightSum - higherWeight );
228 makeOtherPartition( lowerWeightPartition,
229 higherWeightPartition );
231 else if( orderedList.size() < 4 )
238 lowerWeightPartition.push_back( orderedList.back().first );
239 lowerWeight = orderedList.back().second;
240 higherWeight = ( weightSum - lowerWeight );
241 makeOtherPartition( higherWeightPartition,
242 lowerWeightPartition );
253 bestCandidateSoFar = &(vectorManagingCandidateMemory.newEnd());
254 bestCandidateSoFar->getVector().assign( 1,
255 orderedList.back().first );
256 lowerWeight = orderedList.back().second;
257 higherWeight = ( weightSum - lowerWeight );
258 bestCandidateSoFar->setWeight( lowerWeight );
259 bestCandidateSoFar->setInverseWeight( higherWeight );
271 currentCandidate = &(vectorManagingCandidateMemory.newEnd());
274 candidatesToBuildOn.push_back( currentCandidate );
275 currentCandidate->getVector().assign( 2,
276 orderedList.front().first );
278 currentCandidate->getVector()[ 1 ] = listIterator->first;
282 = ( orderedList.front().second + listIterator->second );
286 currentCandidate->setWeight( currentWeight );
287 currentCandidate->setInverseWeight( ( weightSum - currentWeight ) );
289 if( lowerWeight < currentWeight )
294 lowerWeight = currentWeight;
295 higherWeight = ( weightSum - currentWeight );
297 bestCandidateSoFar = currentCandidate;
318 while( orderedList.end() != listIterator )
322 candidateIterator( candidatesToBuildOn.begin() );
323 candidatesToBuildOn.end() != candidateIterator;
324 ++candidateIterator )
326 if( ( 2 * ( (*candidateIterator)->getVector().size() + 1 ) )
327 <= orderedList.size() )
331 currentWeight = ( (*candidateIterator)->getWeight()
332 + listIterator->second );
334 if( halfTotalWeight < currentWeight )
342 if( higherWeight > currentWeight )
350 higherWeight = currentWeight;
351 lowerWeight = ( weightSum - currentWeight );
354 = &(vectorManagingCandidateMemory.newEnd());
356 bestCandidateSoFar->buildFrom( *(*candidateIterator),
367 = candidatesToBuildOn.erase( candidateIterator );
375 if( lowerWeight < currentWeight )
379 lowerWeight = currentWeight;
380 higherWeight = ( weightSum - currentWeight );
383 = &(vectorManagingCandidateMemory.newEnd());
385 bestCandidateSoFar->buildFrom( *(*candidateIterator),
390 if( ( 2 * ( (*candidateIterator)->getVector().size() + 2 ) )
391 <= orderedList.size() )
395 extraCandidates.push_back( bestCandidateSoFar );
398 else if( ( 2 * ( (*candidateIterator)->getVector().size()
400 <= orderedList.size() )
408 = &(vectorManagingCandidateMemory.newEnd());
409 extraCandidates.push_back( currentCandidate );
411 currentCandidate->buildFrom( *(*candidateIterator),
415 ( weightSum - currentWeight ) );
428 candidatesToBuildOn.splice( candidatesToBuildOn.begin(),
435 lowerWeightIterator = orderedList.begin();
436 while( listIterator != lowerWeightIterator )
439 = ( listIterator->second + lowerWeightIterator->second );
440 if( halfTotalWeight < currentWeight )
445 if( higherWeight > currentWeight )
449 higherWeight = currentWeight;
450 lowerWeight = ( weightSum - currentWeight );
453 = &(vectorManagingCandidateMemory.newEnd());
455 bestCandidateSoFar->getVector().assign( 2,
456 lowerWeightIterator->first );
457 bestCandidateSoFar->getVector()[ 1 ] = listIterator->first;
458 bestCandidateSoFar->setWeight( higherWeight );
459 bestCandidateSoFar->setInverseWeight( lowerWeight );
465 lowerWeightIterator = listIterator;
472 currentCandidate = &(vectorManagingCandidateMemory.newEnd());
473 candidatesToBuildOn.push_back( currentCandidate );
475 currentCandidate->getVector().assign( 2,
476 lowerWeightIterator->first );
477 currentCandidate->getVector()[ 1 ] = listIterator->first;
478 currentCandidate->setWeight( currentWeight );
479 currentCandidate->setInverseWeight( ( weightSum
481 if( lowerWeight < currentWeight )
485 lowerWeight = currentWeight;
486 higherWeight = ( weightSum - currentWeight );
488 bestCandidateSoFar = currentCandidate;
492 ++lowerWeightIterator;
508 if( halfTotalWeight > bestCandidateSoFar->getWeight() )
510 fillVectorFromBestCandidate( lowerWeightPartition );
511 makeOtherPartition( higherWeightPartition,
512 lowerWeightPartition );
516 fillVectorFromBestCandidate( higherWeightPartition );
517 makeOtherPartition( lowerWeightPartition,
518 higherWeightPartition );
526 template<
typename ClassToBeSorted >
527 inline std::vector< unsigned int >
const&
541 return lowerWeightPartition;
544 template<
typename ClassToBeSorted >
553 template<
typename ClassToBeSorted >
554 inline std::vector< unsigned int >
const&
568 return higherWeightPartition;
571 template<
typename ClassToBeSorted >
580 template<
typename ClassToBeSorted >
584 lowerWeightPartition.clear();
585 higherWeightPartition.clear();
587 vectorManagingCandidateMemory.clearEntries();
588 candidatesToBuildOn.clear();
591 template<
typename ClassToBeSorted >
599 if( firstPair.second <= secondPair.second )
609 template<
typename ClassToBeSorted >
612 std::vector< unsigned int >& partitionToBeMade )
614 partitionToBeMade = bestCandidateSoFar->getVector();
617 template<
typename ClassToBeSorted >
620 std::vector< unsigned int >& partitionToBeMade,
621 std::vector< unsigned int >& partitionAlreadyMade )
628 alreadyUsedIterator( partitionAlreadyMade.begin() );
629 partitionAlreadyMade.end() > alreadyUsedIterator;
630 ++alreadyUsedIterator )
633 removingIterator = orderedList.begin();
634 while( removingIterator->first != *alreadyUsedIterator )
639 orderedList.erase( removingIterator );
645 orderedList.end() != fillingIterator;
648 partitionToBeMade.push_back( fillingIterator->first );
BalancedPartitioner(double(*weightGetter)(ClassToBeSorted const &))
std::list< IndexWithWeight > orderedList
std::pair< unsigned int, double > IndexWithWeight
static bool orderByDouble(IndexWithWeight const &firstPair, IndexWithWeight const &secondPair)
unsigned int sizeOfVectorToSort
VectorlikeArray< BalancedPartitionCandidate > vectorManagingCandidateMemory
std::list< BalancedPartitionCandidate * >::iterator CandidateListIterator
void makeOtherPartition(std::vector< unsigned int > &partitionToBeMade, std::vector< unsigned int > &partitionAlreadyMade)
std::vector< unsigned int > const & getLowerWeightPartitionIndices() const
std::list< IndexWithWeight >::iterator IndexWithWeightListIterator
std::vector< unsigned int > lowerWeightPartition
std::list< BalancedPartitionCandidate * > candidatesToBuildOn
std::vector< ClassToBeSorted >::iterator ClassToBeSortedIterator
std::list< IndexWithWeight >::const_iterator IndexWithWeightListConstIterator
std::vector< unsignedint >::const_iterator CandidateVectorConstIterator
double getHigherWeight() const
std::vector< unsigned int > higherWeightPartition
double getLowerWeight() const
BalancedPartitionCandidate * currentCandidate
void fillVectorFromBestCandidate(std::vector< unsigned int > &partitionToBeMade)
void makeMinimumDifferencePartition(std::vector< ClassToBeSorted > const &vectorToBeSorted)
double(* weightGetter)(ClassToBeSorted const &)
std::list< BalancedPartitionCandidate * > extraCandidates
BalancedPartitionCandidate * bestCandidateSoFar
std::vector< unsigned int > const & getHigherWeightPartitionIndices() const
void clearSavedCandidates()