a Code for the Combination of Indirect and Direct Constraints on High Energy Physics Models Logo
BalancedPartitioner.hpp
Go to the documentation of this file.
1/*
2 * BalancedPartitioner.hpp
3 *
4 * Created on: Jul 12, 2012
5 * Author: Ben O'Leary (benjamin.oleary@gmail.com)
6 *
7 * This file is part of BOLlib, released under the
8 * GNU General Public License. Please see the accompanying
9 * README.BOLlib.txt file for a full list of files, brief documentation
10 * on how to use these classes, and further details on the license.
11 */
12
13#ifndef BALANCEDPARTITIONER_HPP_
14#define BALANCEDPARTITIONER_HPP_
15
16#include <vector>
17#include <list>
18#include "VectorlikeArray.hpp"
20
21namespace BOL
22{
23 // this template class takes a std::vector of pointers to instances of
24 // ClassToBeSorted & a pointer to a function which takes a const reference to
25 // a ClassToBeSorted instance & returns a double, & partitions the
26 // std::vector according to the doubles returned from the provided
27 // ClassToBeSorted references.
28 // basically this takes a set of objects that have some way of providing
29 // weights as doubles, & finds the set of objects such that the sum of their
30 // their weights is as close to half of the total weight as possible, thus in
31 // effect providing 2 sets with as equal weights as possible.
32 // the output of this class is a vector of unsigned ints which are the
33 // indices of the elements in the original vector which belong to either the
34 // collection with lower or higher weight, depending on whether
35 // getLowerWeightPartitionIndices() or getHigherWeightPartitionIndices() is
36 // called.
37 template< typename ClassToBeSorted >
39 {
40 public:
41 BalancedPartitioner( double (*weightGetter)( ClassToBeSorted const& ) );
43
44 void
46 std::vector< ClassToBeSorted > const& vectorToBeSorted );
47
48 std::vector< unsigned int > const&
50 // this returns a reference to an internally-held std::vector of
51 // unsigned ints corresponding to indices in the vector given to the last
52 // call of makeMinimumDifferencePartition(...). the collection of objects
53 // from that vector with these indices is the partition with GREATEST
54 // weight UNDER (or equal to) half the the total weight of the set of
55 // objects last given to makeMinimumDifferencePartition(...).
56 // NOTE BENE: this std::vector gets OVER-WRITTEN by subsequent calls to
57 // makeMinimumDifferencePartition(...)! if you want to keep the returned
58 // set, you have to make your own *copy* of the std::vector referenced by
59 // the return value of this function.
60 double
61 getLowerWeight() const;
62 // this returns the sum of absolute weights of the objects with indices in
63 // the return reference of getLowerWeightPartitionIndices().
64 std::vector< unsigned int > const&
66 // this returns a reference to an internally-held std::vector of
67 // unsigned ints corresponding to indices in the vector given to the last
68 // call of makeMinimumDifferencePartition(...). the collection of objects
69 // from that vector with these indices is the partition with LEAST weight
70 // OVER (or equal to) half the the total weight of the set of objects last
71 // given to makeMinimumDifferencePartition(...).
72 // NOTE BENE: this std::vector gets OVER-WRITTEN by subsequent calls to
73 // makeMinimumDifferencePartition(...)! if you want to keep the returned
74 // set, you have to make your own *copy* of the std::vector referenced by
75 // the return value of this function.
76 double
77 getHigherWeight() const;
78 // this returns the sum of absolute weights of the objects with indices in
79 // the return reference of getHigherWeightPartitionIndices().
80
81
82 protected:
83 typedef typename std::pair< unsigned int, double > IndexWithWeight;
84 typedef typename
85 std::list< IndexWithWeight >::iterator IndexWithWeightListIterator;
86 typedef typename
87 std::list< IndexWithWeight >::const_iterator
89 typedef typename
90 std::vector< ClassToBeSorted >::iterator ClassToBeSortedIterator;
91 typedef typename
92 std::list< BalancedPartitionCandidate* >::iterator CandidateListIterator;
93 typedef typename
94 std::vector< unsigned int >::const_iterator
96
97 unsigned int sizeOfVectorToSort;
98 // these are the sets of objects with the weight closest to half the total
99 // weight of the given argument set:
100 std::vector< unsigned int > lowerWeightPartition;
102 std::vector< unsigned int > higherWeightPartition;
104 double (*weightGetter)( ClassToBeSorted const& );
105 double weightSum;
107 std::list< IndexWithWeight > orderedList;
108 // this holds indices of the objects to be partitioned, ordered by weight.
114 // this is a vector of candidates for the partitionedVector. it is for
115 // memory management: the actual set of candidates used for finding the
116 // partition is:
117 std::list< BalancedPartitionCandidate* > candidatesToBuildOn;
118 std::list< BalancedPartitionCandidate* > extraCandidates;
119 // this is used to add the candidates from building with a given object to
120 // candidatesToBuildOn after the object has finished looking through
121 // candidatesToBuildOn, to avoid double-counting.
122
123 void
125
126 static bool
127 orderByDouble( IndexWithWeight const& firstPair,
128 IndexWithWeight const& secondPair );
129 // this returns true if firstPair->second <= secondPair->second, false
130 // otherwise.
131
132 void
134 std::vector< unsigned int >& partitionToBeMade );
135 void
136 makeOtherPartition( std::vector< unsigned int >& partitionToBeMade,
137 std::vector< unsigned int >& partitionAlreadyMade );
138 // this REMOVES ALL OF THE PAIRS WITH THE SAME INDICES AS IN
139 // partitionAlreadyMade FROM orderedList & then fills partitionToBeMade
140 // with the indices that remain.
141 };
142
143
144
145
146 template< typename ClassToBeSorted >
147 inline
149 double (*weightGetter)( ClassToBeSorted const& ) ) :
150 sizeOfVectorToSort( 0 ),
151 lowerWeightPartition(),
152 lowerWeight( 0.0 ),
153 higherWeightPartition(),
154 higherWeight( 0.0 ),
155 weightGetter( weightGetter ),
156 weightSum( 0.0 ),
157 positiveWeight( 0.0 ),
158 orderedList(),
159 currentCandidate( NULL ),
160 bestCandidateSoFar( NULL ),
161 currentWeight( 0.0 ),
162 vectorManagingCandidateMemory(),
163 candidatesToBuildOn(),
164 extraCandidates()
165 {
166 // just an initialization list.
167 }
168
169 template< typename ClassToBeSorted >
170 inline
172 {
173 // does nothing.
174 }
175
176 template< typename ClassToBeSorted >
177 inline void
179 std::vector< ClassToBeSorted > const& vectorToBeSorted )
180 {
181 // 1st, we remove all the stuff that might have been hanging around since
182 // the last partitioning:
183 clearSavedCandidates();
184 weightSum = 0.0;
185
186 sizeOfVectorToSort = vectorToBeSorted.size();
187 // next we make a list of the objects with the weights (absolute values, &
188 // we also ignore any objects with zero weight) & find the total weight:
189 for( unsigned int whichIndex( 0 );
190 sizeOfVectorToSort > whichIndex;
191 ++whichIndex )
192 {
193 positiveWeight = (*weightGetter)( vectorToBeSorted[ whichIndex ] );
194 if( 0.0 > positiveWeight )
195 {
196 positiveWeight = -positiveWeight;
197 }
198 if( 0.0 < positiveWeight )
199 {
200 weightSum += positiveWeight;
201 orderedList.push_back( IndexWithWeight( whichIndex,
202 positiveWeight ) );
203 }
204 }
205
206 double const halfTotalWeight( 0.5 * weightSum );
207 if( orderedList.empty() )
208 // if the given set didn't have enough objects to sort...
209 {
210 // the vectors that get returned have already been cleared.
211 lowerWeight = 0.0;
212 higherWeight = 0.0;
213 }
214 else
215 {
216 orderedList.sort( &orderByDouble );
217 // now orderedList is all the objects with non-zero weight, ordered by
218 // their absolute weights.
219
220 if( halfTotalWeight <= orderedList.back().second )
221 // if the object with greatest weight takes up half or more of the
222 // total weight by itself...
223 {
224 // it alone becomes higherWeightPartition.
225 higherWeightPartition.push_back( orderedList.back().first );
226 higherWeight = orderedList.back().second;
227 lowerWeight = ( weightSum - higherWeight );
228 makeOtherPartition( lowerWeightPartition,
229 higherWeightPartition );
230 }
231 else if( orderedList.size() < 4 )
232 // or if the given set was too small to have any non-trivial
233 // partitions...
234 {
235 // the object with greatest weight alone becomes lowerWeightPartition
236 // (if it should become higherWeightPartition, it'll have happened in
237 // the previous if statement):
238 lowerWeightPartition.push_back( orderedList.back().first );
239 lowerWeight = orderedList.back().second;
240 higherWeight = ( weightSum - lowerWeight );
241 makeOtherPartition( higherWeightPartition,
242 lowerWeightPartition );
243 }
244 else
245 // otherwise, we need to check all the required combinations (partitions
246 // of sizes up to half the number of objects, with weights less than half
247 // the total weight, *plus* cases where the weight is over half the total
248 // weight, if removing a single element would bring it back under half
249 // the total weight):
250 {
251 // 1st we note that the highest-weight element on its own is still the
252 // leading candidate partition:
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 );
260 // now bestCandidate so far is the highest-weight element on its own, &
261 // vectorManagingCandidateMemory is holding a pointer to it in case the
262 // bestCandidateSoFar pointer gets set to pointing at a different
263 // partitionCandidate.
264
265
266 // now we start going through candidate partitions which consist of 2
267 // or more elements.
268 IndexWithWeightListConstIterator listIterator( orderedList.begin() );
269 ++listIterator;
270 // listIterator is now at the pair with the 2nd object by weight.
271 currentCandidate = &(vectorManagingCandidateMemory.newEnd());
272 // note where the new partitionCandidate is in memory, so that we can
273 // delete it later.
274 candidatesToBuildOn.push_back( currentCandidate );
275 currentCandidate->getVector().assign( 2,
276 orderedList.front().first );
277 // currentCandidate is now the set { [lowest weight element] }.
278 currentCandidate->getVector()[ 1 ] = listIterator->first;
279 // currentCandidate is now the set
280 // { [lowest weight element], [2nd-lowest weight element] }.
281 currentWeight
282 = ( orderedList.front().second + listIterator->second );
283 // the only way that this combination could have half the weight or
284 // over is if there was only 3 elements or less, which should have
285 // been caught by earlier if statements.
286 currentCandidate->setWeight( currentWeight );
287 currentCandidate->setInverseWeight( ( weightSum - currentWeight ) );
288
289 if( lowerWeight < currentWeight )
290 // if this is a better candidate than the single highest-weight
291 // object...
292 {
293 // note the weights of this new current best candidate:
294 lowerWeight = currentWeight;
295 higherWeight = ( weightSum - currentWeight );
296 // note the actual new best current candidate:
297 bestCandidateSoFar = currentCandidate;
298 }
299
300 IndexWithWeightListConstIterator lowerWeightIterator;
301 // this is used for making new candidates of 2 elements.
302
303 // now we loop over the rest of the objects in orderedList (all but the
304 // 2 lowest-weight objects) to build all partitions with 2 or more
305 // objects.
306 // we don't bother building with partition candidates which are already
307 // over half the total weight; however, we do keep those which are over
308 // half the weight after being built from a candidate with less than
309 // half the weight, if its weight is less that the higherWeight of the
310 // best candidate so far, in which case it becomes the new best
311 // candidate.
312 // we also don't bother building candidates with more than half the
313 // total number of elements, because their partners should already have
314 // been found.
315
316 // move on to the 3rd object by weight to begin the loop:
317 ++listIterator;
318 while( orderedList.end() != listIterator )
319 // until we reach the end of orderedList...
320 {
322 candidateIterator( candidatesToBuildOn.begin() );
323 candidatesToBuildOn.end() != candidateIterator;
324 ++candidateIterator )
325 {
326 if( ( 2 * ( (*candidateIterator)->getVector().size() + 1 ) )
327 <= orderedList.size() )
328 // if we're not building a candidate that consists of too many
329 // objects...
330 {
331 currentWeight = ( (*candidateIterator)->getWeight()
332 + listIterator->second );
333
334 if( halfTotalWeight < currentWeight )
335 // if this candidate is already over half the weight, it cannot
336 // be used to build upon, so we only keep it if it's a better
337 // candidate than bestCandidateSoFar. in either case, we remove
338 // *candidateIterator from candidatesToBuildOn because it's
339 // not going to be a better candidate when paired with an
340 // object of even higher weight.
341 {
342 if( higherWeight > currentWeight )
343 // if this *is* a better candidate (including not consisting
344 // of too many elements; if a candidate has half the elements
345 // but over half the weight, the its partner has half the
346 // elements & less than half the weight, so it'll be found
347 // anyway)...
348 {
349 // note the weights of this new current best candidate:
350 higherWeight = currentWeight;
351 lowerWeight = ( weightSum - currentWeight );
352 // make the new best candidate & manage the memory:
353 bestCandidateSoFar
354 = &(vectorManagingCandidateMemory.newEnd());
355 // set the candidate's properties:
356 bestCandidateSoFar->buildFrom( *(*candidateIterator),
357 listIterator->first,
358 higherWeight,
359 lowerWeight );
360 }
361 // otherwise, we don't do anything with this combination of
362 // *candidateIterator & *listIterator.
363 // in either case we remove *candidateIterator from
364 // candidatesToBuildOn because it's not going to be a better
365 // candidate when paired with an object of even higher weight.
366 candidateIterator
367 = candidatesToBuildOn.erase( candidateIterator );
368 }
369 else
370 // otherwise, currentWeight <= halfTotalWeight, so we check to
371 // see if it's a better candidate than bestCandidateSoFar, &
372 // also if we should keep it for building on, if it does not
373 // consist of too many objects already...
374 {
375 if( lowerWeight < currentWeight )
376 // if this *is* a better candidate...
377 {
378 // note the weights of this new current best candidate:
379 lowerWeight = currentWeight;
380 higherWeight = ( weightSum - currentWeight );
381 // make the new best candidate & manage the memory:
382 bestCandidateSoFar
383 = &(vectorManagingCandidateMemory.newEnd());
384 // set the candidate's properties:
385 bestCandidateSoFar->buildFrom( *(*candidateIterator),
386 listIterator->first,
387 lowerWeight,
388 higherWeight );
389
390 if( ( 2 * ( (*candidateIterator)->getVector().size() + 2 ) )
391 <= orderedList.size() )
392 // if building on this would make a candidate that still
393 // would not consist of too many objects...
394 {
395 extraCandidates.push_back( bestCandidateSoFar );
396 }
397 }
398 else if( ( 2 * ( (*candidateIterator)->getVector().size()
399 + 2 ) )
400 <= orderedList.size() )
401 // otherwise if we're building a candidate which is not the
402 // best candidate so far, but building on it would make a
403 // candidate that still would not consist of too many
404 // objects...
405 {
406 // make the new candidate & manage the memory:
407 currentCandidate
408 = &(vectorManagingCandidateMemory.newEnd());
409 extraCandidates.push_back( currentCandidate );
410 // set the candidate's properties:
411 currentCandidate->buildFrom( *(*candidateIterator),
412 listIterator->first,
413 currentWeight,
414 // we know that ( halfTotalWeight > currentWeight )
415 ( weightSum - currentWeight ) );
416 }
417 }
418 // end of checking if the weight of this combination of
419 // *candidateIterator & *listIterator makes it worth keeping,
420 // either as bestCandidateSoFar or just as a candidate to build
421 // others from.
422 }
423 // end of if the candidate would not consist of too many objects.
424 }
425 // end of for loop over existing candidate partitions to build new
426 // partitions from with (*listIterator)->first
427
428 candidatesToBuildOn.splice( candidatesToBuildOn.begin(),
429 extraCandidates );
430 // all the new candidate partitions are moved from extraCandidates to
431 // candidatesToBuildOn, at the start, though that isn't important.
432
433 // now we need to build all the 2-object candidates with
434 // *listIterator & all objects before it in orderedList:
435 lowerWeightIterator = orderedList.begin();
436 while( listIterator != lowerWeightIterator )
437 {
438 currentWeight
439 = ( listIterator->second + lowerWeightIterator->second );
440 if( halfTotalWeight < currentWeight )
441 // if this candidate is already over half the weight, it cannot
442 // be used to build upon, so we only keep it if it's a better
443 // candidate than bestCandidateSoFar.
444 {
445 if( higherWeight > currentWeight )
446 // if this *is* a better candidate...
447 {
448 // note the weights of this new current best candidate:
449 higherWeight = currentWeight;
450 lowerWeight = ( weightSum - currentWeight );
451 // make the new best candidate & manage the memory:
452 bestCandidateSoFar
453 = &(vectorManagingCandidateMemory.newEnd());
454 // set the candidate's properties:
455 bestCandidateSoFar->getVector().assign( 2,
456 lowerWeightIterator->first );
457 bestCandidateSoFar->getVector()[ 1 ] = listIterator->first;
458 bestCandidateSoFar->setWeight( higherWeight );
459 bestCandidateSoFar->setInverseWeight( lowerWeight );
460 }
461 // otherwise, we don't do anything with this combination of
462 // *lowerWeightIterator & *listIterator, or any other
463 // *lowerWeightIterator, because they'll all have even greater
464 // weight, so we end the loop:
465 lowerWeightIterator = listIterator;
466 }
467 else
468 // otherwise, we have a new candidate to build upon, even if it's
469 // not the best candidate so far...
470 {
471 // make the new candidate & manage the memory:
472 currentCandidate = &(vectorManagingCandidateMemory.newEnd());
473 candidatesToBuildOn.push_back( currentCandidate );
474 // set the candidate's properties:
475 currentCandidate->getVector().assign( 2,
476 lowerWeightIterator->first );
477 currentCandidate->getVector()[ 1 ] = listIterator->first;
478 currentCandidate->setWeight( currentWeight );
479 currentCandidate->setInverseWeight( ( weightSum
480 - currentWeight ) );
481 if( lowerWeight < currentWeight )
482 // if this *is* a better candidate...
483 {
484 // note the weights of this new current best candidate:
485 lowerWeight = currentWeight;
486 higherWeight = ( weightSum - currentWeight );
487 // note the actual new best current candidate:
488 bestCandidateSoFar = currentCandidate;
489 }
490
491 // now we try the next-lowest weight pairing of *listIterator:
492 ++lowerWeightIterator;
493 }
494 // end of if-else deciding whether to create a new candidate & move
495 // on to the next pairing, or to break the loop (possibly after
496 // updating bestCandidateSoFar).
497 }
498 // end of while loop over objects in orderedList before
499 // *listIterator.
500
501 // move on to the next object by weight:
502 ++listIterator;
503 }
504 // end of while loop going over the higher-weighted objects, building
505 // all the partition candidates which can involve them.
506
507 // at this point, bestCandidateSoFar *is* the best candidate:
508 if( halfTotalWeight > bestCandidateSoFar->getWeight() )
509 {
510 fillVectorFromBestCandidate( lowerWeightPartition );
511 makeOtherPartition( higherWeightPartition,
512 lowerWeightPartition );
513 }
514 else
515 {
516 fillVectorFromBestCandidate( higherWeightPartition );
517 makeOtherPartition( lowerWeightPartition,
518 higherWeightPartition );
519 }
520 }
521 }
522 // end of if-else about whether we needed to check all appropriate
523 // combinations or not.
524 }
525
526 template< typename ClassToBeSorted >
527 inline std::vector< unsigned int > const&
529 ) const
530 // this returns a reference to an internally-held std::vector of
531 // unsigned ints corresponding to indices in the vector given to the last
532 // call of makeMinimumDifferencePartition(...). the collection of objects
533 // from that vector with these indices is the partition with GREATEST weight
534 // UNDER (or equal to) half the the total weight of the set of objects last
535 // given to makeMinimumDifferencePartition(...).
536 // NOTE BENE: this std::vector gets OVER-WRITTEN by subsequent calls to
537 // makeMinimumDifferencePartition(...)! if you want to keep the returned
538 // set, you have to make your own *copy* of the std::vector referenced by
539 // the return value of this function.
540 {
541 return lowerWeightPartition;
542 }
543
544 template< typename ClassToBeSorted >
545 inline double
547 // this returns the sum of absolute weights of the objects with indices in
548 // the return reference of getLowerWeightPartitionIndices().
549 {
550 return lowerWeight;
551 }
552
553 template< typename ClassToBeSorted >
554 inline std::vector< unsigned int > const&
556 ) const
557 // this returns a reference to an internally-held std::vector of
558 // unsigned ints corresponding to indices in the vector given to the last
559 // call of makeMinimumDifferencePartition(...). the collection of objects
560 // from that vector with these indices is the partition with LEAST weight
561 // OVER (or equal to) half the the total weight of the set of objects last
562 // given to makeMinimumDifferencePartition(...).
563 // NOTE BENE: this std::vector gets OVER-WRITTEN by subsequent calls to
564 // makeMinimumDifferencePartition(...)! if you want to keep the returned
565 // set, you have to make your own *copy* of the std::vector referenced by
566 // the return value of this function.
567 {
568 return higherWeightPartition;
569 }
570
571 template< typename ClassToBeSorted >
572 inline double
574 // this returns the sum of absolute weights of the objects with indices in
575 // the return reference of getHigherWeightPartitionIndices().
576 {
577 return higherWeight;
578 }
579
580 template< typename ClassToBeSorted >
581 inline void
583 {
584 lowerWeightPartition.clear();
585 higherWeightPartition.clear();
586 orderedList.clear();
587 vectorManagingCandidateMemory.clearEntries();
588 candidatesToBuildOn.clear();
589 }
590
591 template< typename ClassToBeSorted >
592 inline bool
594 IndexWithWeight const& firstPair,
595 IndexWithWeight const& secondPair )
596 // this returns true if firstPair->second <= secondPair->second, false
597 // otherwise.
598 {
599 if( firstPair.second <= secondPair.second )
600 {
601 return true;
602 }
603 else
604 {
605 return false;
606 }
607 }
608
609 template< typename ClassToBeSorted >
610 inline void
612 std::vector< unsigned int >& partitionToBeMade )
613 {
614 partitionToBeMade = bestCandidateSoFar->getVector();
615 }
616
617 template< typename ClassToBeSorted >
618 inline void
620 std::vector< unsigned int >& partitionToBeMade,
621 std::vector< unsigned int >& partitionAlreadyMade )
622 // this REMOVES ALL OF THE PAIRS WITH THE SAME INDICES AS IN
623 // partitionAlreadyMade FROM orderedList & then fills partitionToBeMade with
624 // the indices that remain.
625 {
626 IndexWithWeightListIterator removingIterator( orderedList.begin() );
628 alreadyUsedIterator( partitionAlreadyMade.begin() );
629 partitionAlreadyMade.end() > alreadyUsedIterator;
630 ++alreadyUsedIterator )
631 {
632 // now we look for *alreadyUsedIterator in orderedList:
633 removingIterator = orderedList.begin();
634 while( removingIterator->first != *alreadyUsedIterator )
635 {
636 ++removingIterator;
637 }
638 // now we've found *alreadyUsedIterator in orderedList.
639 orderedList.erase( removingIterator );
640 // we remove it from the list.
641 }
642 // now all the elements of partitionAlreadyMade should have been removed
643 // from orderedList.
644 for( IndexWithWeightListIterator fillingIterator( orderedList.begin() );
645 orderedList.end() != fillingIterator;
646 ++fillingIterator )
647 {
648 partitionToBeMade.push_back( fillingIterator->first );
649 }
650 }
651
652} // end of BOL namespace
653
654#endif /* BALANCEDPARTITIONER_HPP_ */
BalancedPartitioner(double(*weightGetter)(ClassToBeSorted const &))
std::list< IndexWithWeight > orderedList
std::pair< unsigned int, double > IndexWithWeight
static bool orderByDouble(IndexWithWeight const &firstPair, IndexWithWeight const &secondPair)
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
std::vector< unsigned int > higherWeightPartition
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