62 void push(
const T &t);
64 bool empty()
const {
return !curSize;}
91 return array[curSize];
100 void MassTool::preprocessKnapsack(vector<Weight> &weights,
float totalWeight,
float tolerance,
unsigned int maxCombine)
105 vector<bool> badWeight(weights.size(),
false);
106 for(
size_t ui=0;ui<weights.size();ui++)
108 if(weights[ui].mass > totalWeight+tolerance)
118 float tolerance,
unsigned int maxObjects, vector<vector<Weight> > &solutions)
128 preprocessKnapsack(weights,targetWeight,tolerance,maxObjects);
131 const float upperWeight = targetWeight+tolerance;
132 const float lowerWeight = targetWeight-tolerance;
134 std::sort(weights.begin(),weights.end());
138 weightEntry.cumulativeWeight=0;
139 weightEntry.allowableWeights=weights;
142 searchStack.
push(weightEntry);
146 while(!searchStack.
empty())
148 vector<Weight> allowableWeights,curWeights;
150 unsigned insertOffset;
173 float remainingWeight,currentWeight;
174 curWeights.push_back(allowableWeights[insertOffset]);
177 if( currentWeight <=upperWeight && currentWeight >=lowerWeight)
180 solutions.push_back(curWeights);
188 remainingWeight=upperWeight-currentWeight;
189 if(remainingWeight > 0)
191 for(
size_t ui=0;ui<allowableWeights.size();ui++)
193 if(allowableWeights[ui].mass > remainingWeight)
195 allowableWeights.resize(ui+1);
201 allowableWeights.clear();
205 if(allowableWeights.size() && curWeights.size() != maxObjects)
207 weightEntry.curWeights.swap(curWeights);
208 weightEntry.allowableWeights.swap(allowableWeights);
209 weightEntry.cumulativeWeight=currentWeight;
211 weightEntry.offset=insertOffset;
212 searchStack.
push(weightEntry);
221 float tolerance,
unsigned int maxObjects, vector<vector<Weight> > &solutions)
226 if(weights.empty() || targetWeight.empty())
229 float maxWeight=*(std::max_element(targetWeight.begin(),targetWeight.end()));
233 preprocessKnapsack(weights,maxWeight,tolerance,maxObjects);
236 const float upperWeight = maxWeight+tolerance;
238 std::sort(weights.begin(),weights.end());
242 weightEntry.cumulativeWeight=0;
243 weightEntry.allowableWeights=weights;
246 searchStack.
push(weightEntry);
250 while(!searchStack.
empty())
252 vector<Weight> allowableWeights,curWeights;
254 unsigned insertOffset;
277 float remainingWeight,currentWeight;
278 curWeights.push_back(allowableWeights[insertOffset]);
281 for(
unsigned int ui=0;ui<targetWeight.size();ui++)
283 if( currentWeight <= targetWeight[ui]+tolerance &&
284 currentWeight >=targetWeight[ui]-tolerance)
287 solutions.push_back(curWeights);
296 remainingWeight=upperWeight-currentWeight;
297 if(remainingWeight > 0)
299 for(
size_t ui=0;ui<allowableWeights.size();ui++)
301 if(allowableWeights[ui].mass > remainingWeight)
303 allowableWeights.resize(ui+1);
309 allowableWeights.clear();
313 if(allowableWeights.size() && curWeights.size() != maxObjects)
315 weightEntry.curWeights.swap(curWeights);
316 weightEntry.allowableWeights.swap(allowableWeights);
317 weightEntry.cumulativeWeight=currentWeight;
319 weightEntry.offset=insertOffset;
320 searchStack.
push(weightEntry);
329 bool MassTool::runUnitTests()
331 vector<Weight> weights;
332 weights.push_back(1.0);
333 weights.push_back(3.0);
334 weights.push_back(10.0);
339 vector<vector<Weight> > solutions;
340 bruteKnapsack(weights,4.0f,0.01f,4,solutions);
342 TEST(solutions.size() ==2,
"Brute-force knapsack test");
348 weights.push_back(1.0);
349 weights.push_back(3.0);
350 weights.push_back(10.0);
352 vector<float> targetWeights;
353 targetWeights.push_back(4.0f);
354 targetWeights.push_back(10.0f);
355 bruteKnapsack(weights,targetWeights,
358 TEST(solutions.size() ==4,
"Brute-force knapsack test with multiple targets");
void vectorMultiErase(std::vector< T > &vec, const std::vector< bool > &wantKill)
Remove elements from the vector, without preserving order.
vector< Weight > allowableWeights
vector< Weight > curWeights