(file) Return to acm2.cpp CVS log (file) (dir) Up to [RizwankCVS] / acm

  1 rizwank 1.11 #include<stdlib.h>
  2              #include<iostream>
  3              #include<fstream>
  4              #include<string>
  5 rizwank 1.1  #include <queue>
  6 rizwank 1.12 #include <stack>
  7 rizwank 1.13 #include <vector>
  8 rizwank 1.1  #include <stdio.h>
  9 rizwank 1.15 
 10 rizwank 1.11 using namespace std;
 11              
 12 rizwank 1.15 //threading might be useful except for the fact that our target machine is likely to have a single processor
 13              // what about task limiting from SEAS?
 14              // actually sparc machines on ugrad  are multiple processor -- could I thread/fork the calculations? would overhead > savings
 15              // also if i was really stingy, I could revert to the arrays I had before, make them dynamic and create a copy ctor for key
 16              // of course, vector<bool> packs 8 bools in a byte, arrays dont
 17 rizwank 1.14 
 18 rizwank 1.11 typedef long ITEM_MASS;
 19 rizwank 1.9  typedef long INDEX_TYPE;
 20              
 21              
 22 rizwank 1.1  using namespace std;
 23              
 24              // ******************************************************************
 25              // * CLASS : item													*
 26              // * Container object with all the data for a particular item		*
 27              // ******************************************************************
 28 rizwank 1.15 
 29              //since items are no longer special in any way, I could actually just use a vector now!
 30              // would this be any faster?
 31              
 32 rizwank 1.1  class item {
 33              public:
 34 rizwank 1.9  	ITEM_MASS getWeight();
 35 rizwank 1.10 	void setData(ITEM_MASS);
 36 rizwank 1.1  private:
 37 rizwank 1.9  	ITEM_MASS weight;
 38 rizwank 1.1  };
 39              
 40              // ******************************************************************
 41              // * CLASS : backpack												*
 42              // * Container object with all the data for an entire knapsack		*
 43              // * Full declaration follows, partial declare here for key			*
 44              // ******************************************************************
 45              class backpack;
 46              
 47              // ******************************************************************
 48              // * CLASS : key													*
 49              // * Container object with all the data for the equivalent of a node*
 50              // * on the state space tree										*
 51              // * To allow data to remain private (and decrease the need of data *
 52              // * such as max_weight and total_items to be passed along with		*
 53              // * every function call, a pointer to the containing backpack is	*
 54              // * instead implemented.											*
 55              // ******************************************************************
 56              class key {
 57              public:
 58              	void initKey( backpack *);
 59 rizwank 1.1  	void flagNext();
 60              	void addCurItem();
 61              	bool doneItems();
 62 rizwank 1.15 	ITEM_MASS getBound();
 63 rizwank 1.9  	bool checkItem(INDEX_TYPE);
 64              	ITEM_MASS getWeight();
 65 rizwank 1.1  private:
 66              	void calcBound();
 67 rizwank 1.15 	vector<bool> inserted;
 68              	// replace with a vector! this allows us to remove MAX_ITEMS without the fussyness of copying the
 69              	// contents of a pointer etc like before!
 70              	// bool inserted[MAX_ITEMS];
 71 rizwank 1.9  	INDEX_TYPE nextitem;
 72              	ITEM_MASS cur_weight;
 73 rizwank 1.15 	ITEM_MASS upper_bound;
 74 rizwank 1.1  	backpack *myBackpack;
 75              };
 76              
 77              // ******************************************************************
 78              // * STRUCT : item_comparator										*
 79              // * Functor for comparing the ratio between items					*
 80              // ******************************************************************
 81              struct item_comparator {
 82              	bool operator()( item left, item right ) const 
 83 rizwank 1.8  //	{ return ( left.getRatio() < right.getRatio() ) ; }  
 84 rizwank 1.15 //	{ return ( left.getWeight() < right.getWeight() ); } 
 85              	{return 0;}
 86              	// larger boxes are preferable to smaller boxes
 87              	// removes the need for sort at beginning. 
 88              	// this actually massively increases the time cost for my sample set. defaulting to dumb sort 
 89 rizwank 1.1  } ;
 90              
 91              // ******************************************************************
 92              // * STRUCT : key_comparator										*
 93              // * Functor for comparing the bound between items					*
 94              // ******************************************************************
 95              struct key_comparator {
 96              	bool operator()( key left, key right ) const 
 97              	{ return ( left.getBound() < right.getBound() ) ; } 
 98              } ;
 99              
100              // ******************************************************************
101              // * CLASS : backpack												*
102              // * Container object with all the data for an entire knapsack		*
103              // ******************************************************************
104              class backpack {
105              public:
106 rizwank 1.9  	void initBackpack(INDEX_TYPE, ITEM_MASS);
107 rizwank 1.15 	void changeBackpack(INDEX_TYPE);
108 rizwank 1.10 	void putItem(ITEM_MASS);//, ITEM_MASS);
109 rizwank 1.1  	void store_item_array();
110 rizwank 1.11 	void branch_and_bound(int,ITEM_MASS);
111 rizwank 1.9  	ITEM_MASS get_totalItems();
112              	ITEM_MASS get_maxWeight();
113              	item get_Item(INDEX_TYPE);
114 rizwank 1.1  private:
115              	priority_queue< item, vector<item> , item_comparator> item_queue;
116              	item *item_array;
117              	priority_queue< key, vector<key>, key_comparator> key_queue;
118 rizwank 1.9  	INDEX_TYPE totalItems;
119              	ITEM_MASS maxWeight;
120 rizwank 1.1  	long addnodeCount, worknodeCount;
121              };
122              
123              
124              
125              // ******************************************************************
126              // * FUNCTION : initKey		IN : CLASS key							*
127              // * Initalizes a key, setting the backpack pointer and inital		*
128              // * values then calculating the bound.								*
129              // ******************************************************************
130              void key::initKey(backpack *theCaller){
131              	this->myBackpack = theCaller;
132              	this->nextitem=0;
133              	this->cur_weight=0;
134              	this->calcBound();
135              }
136              
137              // ******************************************************************
138              // * FUNCTION : flagNext		IN : CLASS key						*
139              // * Modifies the key by setting the next item as not inserted but	*
140              // * as processed, then updates the bound.							*
141 rizwank 1.1  // ******************************************************************
142              void key::flagNext(){
143 rizwank 1.15 //	this->inserted[this->nextitem]= 0;
144              	this->inserted.push_back(0);
145 rizwank 1.1  	nextitem++;
146              	this->calcBound();
147              }
148              
149              // ******************************************************************
150              // * FUNCTION : addCurItem		IN : CLASS key						*
151              // * Follows up flagNext by actually marking the last item as		*
152              // * inserted, adding values and weights, then recalcing the bound.	*
153              // ******************************************************************
154              void key::addCurItem(){
155              	nextitem--;
156 rizwank 1.15 	this->inserted.push_back(1);
157              //	this->inserted[this->nextitem]=1;
158 rizwank 1.1  	this->cur_weight += (this->myBackpack->get_Item(this->nextitem)).getWeight();
159              	nextitem++;
160              	this->calcBound();
161              }
162              
163              // ******************************************************************
164              // * FUNCTION : doneItems		IN : CLASS key						*
165              // * Returns TRUE if all the items have been processed				*
166              // ******************************************************************
167              bool key::doneItems(){
168              	return ( this->myBackpack->get_totalItems() == this->nextitem );
169              }
170              
171              // ******************************************************************
172              // * FUNCTION : getBound		IN : CLASS key						*
173              // * Returns the bound.												*
174              // ******************************************************************
175 rizwank 1.15 ITEM_MASS key::getBound(){
176 rizwank 1.1  	return this->upper_bound;
177              }
178              
179              // ******************************************************************
180              // * FUNCTION : calcBound		IN : CLASS key						*
181              // * Calculates the bound. If there are no more items, the bound	*
182              // * remains unchanged. Else, perform the calcuations.				*
183              // * If the weight is over max_weight, set the bound to 0			*
184              // ******************************************************************
185              void key::calcBound(){
186 rizwank 1.14 	ITEM_MASS temp;
187 rizwank 1.1  	if (this->doneItems()) {
188              		temp = 0;
189              	}
190              	else {
191 rizwank 1.14 		temp = ((this->myBackpack->get_maxWeight()) - cur_weight);
192 rizwank 1.1  	}
193 rizwank 1.14 	this->upper_bound = cur_weight + temp;
194 rizwank 1.1  
195              	// What about if the bag is overloaded?
196 rizwank 1.14 	if (this->cur_weight > this->myBackpack->get_maxWeight() ){
197 rizwank 1.1  		this->upper_bound = 0;		// invalidate it, will never reach 0 in bound
198              	}
199              }
200              
201              
202              // ******************************************************************
203              // * FUNCTION : checkItem		IN : CLASS key						*
204              // * Checks if a given item is listed as inserted.					*
205              // ******************************************************************
206 rizwank 1.9  bool key::checkItem(INDEX_TYPE num) {
207 rizwank 1.1  	return (this->inserted[num]);
208              }
209              
210              // ******************************************************************
211              // * FUNCTION : getWeight		IN : CLASS key						*
212              // * Gets the Weight of the current key.							*
213              // ******************************************************************
214 rizwank 1.9  ITEM_MASS key::getWeight(){
215 rizwank 1.1  	return this->cur_weight;
216              }
217              
218              // ******************************************************************
219              // * FUNCTION : getWeight		IN : CLASS item						*
220              // * Gets the Weight of the current item.							*
221              // ******************************************************************
222 rizwank 1.9  ITEM_MASS item::getWeight(){
223 rizwank 1.1  	return this->weight;
224              }
225              
226              
227              // ******************************************************************
228              // * FUNCTION : setData			IN : CLASS item						*
229              // * Sets all the data for an item.									*
230              // ******************************************************************
231 rizwank 1.10 void item::setData(ITEM_MASS weightage){ //, ITEM_MASS costage, ITEM_MASS numerage){
232 rizwank 1.14 //	this->cost = weightage; //costage;
233 rizwank 1.1  	this->weight = weightage;
234 rizwank 1.7  //	this->ratio = ( (float)(cost)/(float)(weight) );
235 rizwank 1.8  //	this->ratio = 1; //ratio = 1
236 rizwank 1.9  //	this->number = numerage;
237 rizwank 1.1  }
238              
239              
240              // ******************************************************************
241              // * FUNCTION : initBackpack	IN : CLASS backpack					*
242              // * Initalizes the backpack values and creates the item array		*
243              // ******************************************************************
244 rizwank 1.9  void backpack::initBackpack(INDEX_TYPE total, ITEM_MASS max){
245 rizwank 1.15 	this->maxWeight = max;
246 rizwank 1.1  	this->totalItems = total;
247              	item_array = new item[total];
248              	worknodeCount = 0;
249              	addnodeCount = 0;
250              }
251              
252 rizwank 1.15 
253              
254 rizwank 1.1  // ******************************************************************
255              // * FUNCTION : putItem			IN : CLASS backpack					*
256              // * Creates an item and places it into the priority queue			*
257              // ******************************************************************
258 rizwank 1.10 void backpack::putItem(ITEM_MASS weight){  //,  ITEM_MASS cost){
259 rizwank 1.1  	item temp_item;
260 rizwank 1.10 	temp_item.setData(weight);//,cost);//,(int)(this->item_queue.size())+1); // sometimes this starts at 2000?
261 rizwank 1.1  	this->item_queue.push(temp_item);
262              }
263              
264              // ******************************************************************
265              // * FUNCTION : store_item_array IN : CLASS backpack				*
266              // * Dumps the Item Queue in order into an Array for Rand. Access	*
267              // ******************************************************************
268              void backpack::store_item_array(){
269              	this->item_array = new item[this->totalItems];
270              	for ( int i = 0; this->totalItems > i; i++){
271              		this->item_array[i] = this->item_queue.top();
272              		this->item_queue.pop();
273              	}
274              }
275              
276              // ******************************************************************
277              // * FUNCTION : get_totalItems	IN : CLASS backpack					*
278              // * Returns the number of items for consideration.					*
279              // ******************************************************************
280 rizwank 1.9  ITEM_MASS backpack::get_totalItems(){
281 rizwank 1.1  	return this->totalItems;
282              }
283              
284              // ******************************************************************
285              // * FUNCTION : get_maxWeight	IN : CLASS backpack					*
286              // * Returns the maximum weight for this backpack.					*
287              // ******************************************************************
288 rizwank 1.9  ITEM_MASS backpack::get_maxWeight(){
289 rizwank 1.1  	return this->maxWeight;
290              }
291              
292              // ******************************************************************
293              // * FUNCTION : get_Item		IN : CLASS backpack					*
294              // * Returns a particular item from the item array					*
295              // ******************************************************************
296 rizwank 1.9  item backpack::get_Item(INDEX_TYPE index){
297 rizwank 1.1  	return ( this->item_array[index] );
298              }
299              
300              // ******************************************************************
301              // * FUNCTION : branch_and_bound IN : CLASS backpack				*
302              // * Performs Best-First-Fit Branch and Bound on this backpack		*
303              // * while keeping track of the nodecounts.							*
304              // * Create a template key with the best possible bound.			*
305              // * Place that key into the queue and start a loop					*
306              // * As long as the 'onwards' flag is TRUE, repeat:					*
307              // *	Take the topmost (highest bound) key out of the queue.		*
308              // *	If that bound has all of its items processed, clear ownards	*
309              // *	Else, create two keys from the original key					*
310              // *	One without the next item and one with.						*
311              // *	Place the new keys into the queue and discard the current	*
312              // *	Repeat														*
313              // * If the loop is ended, the top item on the queue is the best	*
314              // * possible solution for this knapsack.							*
315              // * Fetch all the information and print it out.					*
316              // ******************************************************************
317 rizwank 1.11 void backpack::branch_and_bound(int DEBUG_MODE, ITEM_MASS targetvalue){
318 rizwank 1.1  	key temp_key;
319              	
320              	temp_key.initKey(this);
321              	this->key_queue.push(temp_key);
322              	this->addnodeCount++;
323              
324              	bool onwards = 1;
325              	do
326              	{
327              		temp_key = key_queue.top();
328              		this->key_queue.pop();
329 rizwank 1.14 /*Early skip here -- MASSIVE speed improvements */
330              		if ( temp_key.getWeight() == targetvalue ) {
331 rizwank 1.15 			//printf("Early value acquired! %d\n",temp_key.getWeight() );
332 rizwank 1.14 			goto early; // yes thats a go to. Its the only way to leave and keep the context right. I know its horrible
333              		}
334 rizwank 1.15 //		printf("reached %d\n",temp_key.getWeight());
335 rizwank 1.1  		if ( temp_key.doneItems() ) {
336              			onwards = 0;
337              		}
338              		else {
339 rizwank 1.15 //			this->worknodeCount++;
340 rizwank 1.1              temp_key.flagNext();
341                              this->key_queue.push(temp_key);
342 rizwank 1.15 //				this->addnodeCount++;
343              	
344 rizwank 1.14 				// try this --- compare quicksorted before and after because of greedy grabbing largest
345              				//should find other comparator for weight with sub data like ... pct done
346              						
347 rizwank 1.1  			temp_key.addCurItem();
348 rizwank 1.15 			if (temp_key.getBound() != 0){ 		//insert only if active.
349 rizwank 1.1  				this->key_queue.push(temp_key);
350 rizwank 1.15 //				this->addnodeCount++;
351 rizwank 1.1  			}
352              		}
353 rizwank 1.15 		// commenting out worknode trackerincreases speed by 3%
354 rizwank 1.1  	}
355              	while (onwards);
356              
357 rizwank 1.14 	early:	if (DEBUG_MODE) {
358 rizwank 1.11 		printf("Case n=%2d Total possible nodes in thie state space tree is 2^%2d-1\n",this->totalItems,this->totalItems);
359 rizwank 1.15 		printf("          DISABLED Number of nodes placed in the priority queue: %6d\n",this->addnodeCount);
360              		printf("          DISABLED Number of nodes examined/split:               %6d\n",this->worknodeCount);
361 rizwank 1.11 	}
362              
363 rizwank 1.12 	if ( temp_key.getWeight() == targetvalue ) {
364 rizwank 1.11 		int totalitemsinserted = 0;
365              		int first=1;
366              		for (int i = 0; this->totalItems > i; i++) {
367              			if ( temp_key.checkItem(i) ) {
368              				if (first==0) { printf(","); } 
369              				else {first = 0;}                     // there has GOT to be a better way!
370              				printf("%d", this->item_array[i].getWeight());
371              			}
372              		}
373 rizwank 1.12 	}
374              	else { printf("CANNOT FILL PALLET\n"); }
375 rizwank 1.11 }
376 rizwank 1.13 	
377 rizwank 1.15 void super_increase_algo ( vector<ITEM_MASS> inventory, ITEM_MASS target_value , int DEBUG_MODE ) {
378 rizwank 1.13 	stack<ITEM_MASS> packages_to_load;
379 rizwank 1.15 	INDEX_TYPE size_inventory = inventory.size();
380 rizwank 1.1  
381 rizwank 1.13 	if (DEBUG_MODE) {
382              		printf("Extracting values, highest to lowest, doing reduction from index %d\n",size_inventory);
383              	}
384              	for ( INDEX_TYPE store_index=size_inventory-1; store_index>=0;store_index-- ) {
385              		if (DEBUG_MODE) {
386              			printf("value %d, is it smaller than %d? If so, subtract and store.\n",inventory[store_index],target_value);
387              		}
388              		if ( inventory[store_index] <= target_value ) {
389              			target_value = target_value - inventory[store_index];
390              			packages_to_load.push(inventory[store_index]);
391              		}
392              	}
393              	if ( target_value == 0 ) {
394              		int first = 1;
395              		while ( ! packages_to_load.empty() ) {
396              			if (first==0) { printf(","); } 
397              			else {first = 0;}                     // there has GOT to be a better way!			
398              			printf("%d",packages_to_load.top());
399              			packages_to_load.pop();
400              		}
401              		printf("\n");
402 rizwank 1.13 	}
403              	else { printf("CANNOT FILL PALLET\n"); }
404              }
405              		
406              		
407 rizwank 1.11 void syntaxmsg(){
408              	printf("Usage:\n");
409              	printf("<program name> <input filename> <D/d>\n");
410              	printf("input contains a series of integers [A], comma delimited,\n\t followed by a CR and an int [B]\n");
411              	printf("program outputs a comma delimited list of elements of A that sum to B,\n\t or CANNOT FILL PALLET\n");
412              	printf("Program written for the UCLA ACM Feb 2005 Coding Competition\n");
413              	printf("Dervied from previous academic work written by the author\n(C) 2002-2005 Rizwan Kassim\n");
414              	printf("If the second argument is a D or d, verbose debugging mode will be enabled\n\n");
415              	return;
416 rizwank 1.1  }
417              
418 rizwank 1.14 
419              ITEM_MASS masscomp (const void * a, const void * b)
420              {
421                return ( *(ITEM_MASS*)a - *(ITEM_MASS*)b );
422              }
423              
424              
425 rizwank 1.1  // ******************************************************************
426              // * FUNCTION : main												*
427              // * Initalizes the backpack and the items inside.					*
428              // * Copies those items into an array, prints out the items.		*
429              // * Run the branch_and_bound method.								*
430              // ******************************************************************
431              int main(int argc, char *argv[])
432              {
433              	item temp_item;
434 rizwank 1.11 	int DEBUG_MODE = 0;
435 rizwank 1.1  
436 rizwank 1.11 	if ( argc < 2 ) { syntaxmsg(); return 2;}
437              	if ( argc > 4 ) { syntaxmsg(); return 3;}
438              	if ( argc == 3 ) {
439              		if ( argv[2][0] == 'D' || argv[2][0] == 'd' ) {
440              		printf("Debug switch caught, outputing debug messages\n");
441              		DEBUG_MODE =1; 
442              		} else { syntaxmsg(); return 4;}
443              	}
444              		
445              	if (DEBUG_MODE) {
446              		printf("Entry into UCLA ACM Feb. 2005 Coding Competition\n");
447              		printf("Based on code developed (myself) for CS331 Project 4 at CSU Pomona\n"); 
448              		printf("Version 4\n");
449              		printf("All compiled / source code are (C) Rizwan Kassim 2005\n\n");
450              	}
451              	
452              	ifstream inputfs;
453              	inputfs.open (argv[1]);
454              	if (!inputfs.is_open())
455              	  { printf("File open of %s failed!\n", argv[1]);
456              		syntaxmsg(); 
457 rizwank 1.11 		return 1; }
458              	if (DEBUG_MODE) {
459              		printf("File %s Open!\n",argv[1]);
460              	}
461              	
462              	INDEX_TYPE length;
463              	inputfs.seekg (0, ios::end);
464              	length = inputfs.tellg();
465              	inputfs.seekg (0, ios::beg);
466              	
467              	char * read_buffer = (char *) malloc (length);
468 rizwank 1.13 	vector<ITEM_MASS> inventory;
469 rizwank 1.12 		// could use stack instead of array --- doesn't require malloc, more 'safe' avoids overflows, esp if 
470              		// input file is funky --- its better software engineering, but its slower. Given that this is a pretty
471 rizwank 1.13 		// small system, I'll stick with the array --- oh even better -- a vector!
472 rizwank 1.14 		//http://theory.stanford.edu/~amitp/rants/c++-vs-c/ Vector speed sorting is optimized by using vector!
473 rizwank 1.11 	inputfs.getline (read_buffer, length-1);
474              
475              	char * theToken; INDEX_TYPE index = 0;
476              	theToken=strtok(read_buffer,",");
477              	// assume 1+ items
478              	while ( theToken != NULL ) {
479              		//printf("tokendebug %d %f\n",theToken,theToken);
480 rizwank 1.13 		inventory.push_back(atol(theToken));
481 rizwank 1.11 		//printf("index %d, token %s, value %d\n",index,theToken,inventory[index]);
482              		index++;
483              		theToken = strtok (NULL,",");
484              		}
485 rizwank 1.1  
486 rizwank 1.12 	
487              	int SUPER_MODE = 0;
488 rizwank 1.13 	if (inventory[0]==1) { SUPER_MODE=1;}
489 rizwank 1.1  
490 rizwank 1.11 	if (DEBUG_MODE) {
491 rizwank 1.15 		printf("Line 1 read - %d products from warehouse\n", inventory.size());
492 rizwank 1.12 		if (SUPER_MODE) printf("Working in Superincreasing mode!\n");
493 rizwank 1.11 	}
494              	
495 rizwank 1.14 //	sort (inventory.begin(), inventory.end(),std::greater<ITEM_MASS>() );
496 rizwank 1.15 //	sort (inventory.begin(), inventory.end()); // most efficient, uses largest boxes inherently
497              
498 rizwank 1.11 	// NEED TRY/CATCH error handling for possible segfault locations
499              	inputfs.getline (read_buffer, length-1);	
500 rizwank 1.15 	ITEM_MASS palette_size=atol(read_buffer);
501 rizwank 1.11 	
502              	if (DEBUG_MODE) {
503              		printf("Line 2 read - %d weight units can fit onto palette\n",palette_size);
504              	}
505 rizwank 1.15 
506              	inputfs.close();
507              	free(read_buffer);
508              	
509              
510              // I could use a class to extrapolate out the file loading function like my 499 project....	 
511 rizwank 1.11 	
512 rizwank 1.15 			
513 rizwank 1.13 	if (SUPER_MODE) {
514 rizwank 1.15 		 super_increase_algo (inventory, palette_size , DEBUG_MODE );
515 rizwank 1.13 		 return 0;
516              	 }
517 rizwank 1.15 
518              // filter out oversizes BEFORE we insert them above, therefore making life complicated
519              	 
520              	vector<ITEM_MASS>::iterator itInventory;
521              	
522              //	printf("inventory before %d\n",inventory.size());
523              	for(itInventory = inventory.begin(); itInventory != inventory.end(); itInventory++) {
524              		if (*itInventory > palette_size ) {
525              //			printf("%d removing at , left %d!\n",*itInventory,inventory.size());
526              			inventory.erase(itInventory);
527              			itInventory--;
528              //			printf("%d removed at %d,  left!\n",*itInventory,inventory.size());
529              		// remove elements that are too large. its a n increase here, but >>n increase if done later
530              		}
531              	}
532              
533 rizwank 1.11 	backpack knapsackOne;
534 rizwank 1.9  
535 rizwank 1.15 	knapsackOne.initBackpack(inventory.size(),palette_size);
536 rizwank 1.11 	if (DEBUG_MODE) {
537 rizwank 1.15 		printf("init %d, %d\n",inventory.size(),palette_size);
538              	}
539              	
540              	for(itInventory = inventory.begin(); itInventory != inventory.end(); itInventory++) {
541              		knapsackOne.putItem(*itInventory);
542              //		if (DEBUG_MODE) {
543              //			printf("insert %d\n",*itInventory);
544              //		}
545 rizwank 1.11 	}
546              		
547 rizwank 1.1  	knapsackOne.store_item_array();
548 rizwank 1.13 	inventory.clear();
549 rizwank 1.15 	
550 rizwank 1.11 	knapsackOne.branch_and_bound(DEBUG_MODE,palette_size);
551 rizwank 1.1  
552              	printf("\n");
553              }
554              
555              
556 rizwank 1.12 
557              
558              
559              
560              
561              
562 rizwank 1.1  /* 
563              Modifications to the original branch-and-bound algorithim/approach
564              
565              This program was to compute the maximum value that can be fit into a bag --- Using Levitin p380 for reference
566              right now. As our problem is actually a SUBSET of the given problem ,we can simplify some of the functions.
567              We also don't want any packs too small, but we'll let this compute, see how big the state tree is versus
568              an alternative algorithm.
569              
570              	knapsackOne.initBackpack(5,17); // 5 total items, 17 total weight
571              	knapsackOne.putItem(4,1);
572              	knapsackOne.putItem(7,1);
573              	knapsackOne.putItem(5,1);
574              	knapsackOne.putItem(9,1);
575              	knapsackOne.putItem(1,1);
576              
577              For given same, 2^5-1 possible nodes in tree, 14 nodes placed, 7 split.
578              
579              Lets try something larger. n=10 1,2,3,4,5,6,7,8,9,10 => 18
580              
581              Oooh, we can vary the max backpack item count to only use a certain amount of the items!
582              
583 rizwank 1.1  Whats interesting is that we can keep the various ratio calculations, as we WOULD rather insert an item of 10 lbs rather than 1
584              We just equate weight and value later on! (Or set a fixed ratio of 1)		
585 rizwank 1.2  		knapsack insert (value,value)
586              		
587              		This was max 2^10-1 with only 47 nodes and 33 splits.
588 rizwank 1.1  		
589 rizwank 1.2  And lets try with a random set of 25 numbers!
590              70,76,55,17,70,77,52,81,11,31,57,47,93,53,83,33,1,59,29,33,78,79,37,26,83 ==> 200
591 rizwank 1.5  Chose:
592                            1           70           70
593                            3           55           55
594                           24           26           26
595                           23           37           37
596                           17            1            1
597                            9           11           11
598              2^25-1 worst case, 142 nodes, 115 split!
599              real    0m0.036s
600              user    0m0.030s
601              sys     0m0.030s
602              
603 rizwank 1.2  
604              
605              
606              then 50:
607              186,130,132,108,112,39,90,88,105,172,50,46,125,79,22,192,139,132,77,195,21,129,134,76,179,89,32,55,61,160,49,191,153,86,45,16,196,109,1,178,51,104,40,88,135,100,108,182,30,48  => 1470
608 rizwank 1.5  2^50 worst case, 1826 nodes, 1443 splits
609              real    0m0.044s
610              user    0m0.062s
611              sys     0m0.000s
612              
613 rizwank 1.7  
614 rizwank 1.5  Now, lets really ramp it up so that we can see optimzation effects
615              n=2500! won't even care to list the numbers, no point!
616              
617              Wait, we exceeded 3 minutes there (our weight size was just a guess, btw, might not actually ahve a value)
618              Oh, our memory bound was maxed out so it hit a loop ... it actually completed in less than a sec! God bless my processor :)
619 rizwank 1.6  Lets bump it up to 5k, 
620              
621              Case n=5000 Total possible nodes in thie state space tree is 2^5000-1
622                        Number of nodes placed in the priority queue:  35037
623                        Number of nodes examined/split:                34942
624              
625              real    0m2.810s
626              user    0m1.843s
627              sys     0m0.062s
628              
629              
630              Given that this is about the largest we can hope to achieve before INTMAX because a massive issue (we should really typedefine the container class), lets see what optimizations we can make to this code!
631 rizwank 1.2  
632 rizwank 1.7  must do 1 - 
633 rizwank 1.9  move all the ITEM_MASSs to (other)
634              the ITEM_MASSs are now ITEM_TYPE, a def earlier on (we could have done typedef here too, of course)
635 rizwank 1.7  real    0m2.928s
636              user    0m1.999s
637              sys     0m0.061s
638              Slight increase.
639              
640              Bad things happen when we try to make it into floats, I just tired. floats can't be [] contents for an array ;p
641              Doing unsigned long for now.
642              goal 1 = stop ratio calculation and comparisons if at all possible!
643              real time shot up!
644              real    0m3.994s
645              user    0m2.390s
646              sys     0m0.046s
647              
648 rizwank 1.8  (that being said, timse don't seem to be consistent. CVS is storing our versions, lets plow on)
649              
650              remove the comparator in the structcomparator
651              real    0m2.830s
652              user    0m2.030s
653              sys     0m0.015s
654              
655              remove the printout of the items as inserted
656              real    0m1.423s
657              user    0m1.436s
658              sys     0m0.015s
659              
660 rizwank 1.9  remove the tracking of the item "number", we don't need to deal with it with this project.
661              
662              after moved all unsigned ints to typedefs, 
663              typedef float ITEM_MASS;
664              typedef long INDEX_TYPE;
665              
666              and modified the printfs to handle floating !
667              
668              real    0m1.591s
669              user    0m1.562s
670              sys     0m0.000s
671              		
672              inserting a float does :
673              				
674              acm2.cpp: In function `int main(int, char**)':
675              acm2.cpp:410: error: no matching function for call to `backpack::putItem(
676                 double, int, int)'
677              acm2.cpp:279: error: candidates are: void backpack::putItem(float, float)
678              make: *** [acm2] Error 1
679 rizwank 1.8  
680 rizwank 1.9  (and it locks up if we have a decimal in seeked value)
681 rizwank 1.8  
682 rizwank 1.10 ok we move onwards to remove weight,value calls and replace them with just weight
683              we also use notepad/sed to remove half the sample knapsack calls
684              we realize in doing this that we've actually got 7009 elements! modifiying appropraite values!
685              
686              real    0m2.627s
687              user    0m2.624s
688              sys     0m0.000s
689              
690              but now it uses all 17.
691              
692              
693              Lets try an appropriately high value instead of the 50000ish we're using now. Lets say, we want ... 
694              600 elements of 7000, at avg value of 5000 3000000ish?
695              
696              Case n=6998 Total possible nodes in thie state space tree is 2^6998-1
697                        Number of nodes placed in the priority queue:  70797
698                        Number of nodes examined/split:                69811
699              
700              Totals: 114     509283.00       509283.00
701              
702              then...
703 rizwank 1.10 
704              ============================ KNAPSACK ONE ================================
705              Case n=6998 Total possible nodes in thie state space tree is 2^6998-1
706                        Number of nodes placed in the priority queue: 108848
707                        Number of nodes examined/split:                96391
708              
709              Totals: 1002    5091283.00      5091283.00
710              
711              
712              real    0m9.526s
713              user    0m9.249s
714              sys     0m0.203s
715              
716              
717              I'm actually pretty happy with this. We havent tested a few conditions, but its time we got the file loading routine in
718              
719              
720              todo 
721              1) when it doesnt work
722              2) when its already reached stop
723              3) float
724 rizwank 1.10 
725 rizwank 1.11 For superincreasing sets, its INCREDIBLY easy to do
726              Sort it.
727              if (current value < pallete size), palletsize-current value, current_value on board.
728              repeat until end
729              
730              
731              
732              === loading file now
733              make input float ok
734              
735              reverted to base type of non float --- making the stored value float did badthings to atoi / atof (they didnt work)
736 rizwank 1.10 
737 rizwank 1.8  
738              we could really move the pqueue to a queue --- although don't we want to push bigger items to the top to fill it up faster?
739 rizwank 1.7  
740              goal 1 - lets remove the double call to the creator function, weight=value ratio=1		
741 rizwank 1.2  
742 rizwank 1.14 
743              large set time :
744              103,199,67,119,152,119,181,85,74,73,130,82,79,98,99,95,101,81,54,129,157,88,177,97,122,74,46,77,142,39,61,13,86,173,83,180,49,196,144,101,43,28,3,139,127,149,64,194,18,168,75,89,110,113,113,183,124,4,143,61,70,162,161,101,75,47,51,28,4,149,44,58,131,36,53,18,118,89,37,12,99,38,189,98,164,65,109,190,103,113,160,51,113,130,113,50,26,138,153,196,80,193,40,197,52,195,190,97,108,111,141,2,180,5,125,139,38,21,60,148,191,158,169,50,155,167,152,25,154,3,11,1
745              
746              real    1m14.327s
747              user    1m11.530s
748              sys     0m0.421s
749              
750              with goto removed.
751              
752              
753              largeset time with early leave!
754              Early value acquired! 13273
755              133,103,105,199,33,67,119,119,181,85,74,73,26,130,82,79,98,99,95,101,81,54,129,157,88,177,97,122,74,46,77,142,39,61,13,86,173,83,180,49,196,144,101,43,28,3,139,127,149,64,194,18,168,75,89,110,113,113,183,124,4,143,61,70,162,161,101,75,47,51,28,4,149,44,58,131,36,53,18,118,89,37,12,99,38,189,98,164,65,109,190,103,113,160,51,113,130,113,50,26,138,153,196,80,193,40,197,52,195,190,97,108,111,141,2,180,5,53,125,139,38,21,60,148,191,158,169,50,155,167,25,86,24,3,10
756              
757              real    0m2.594s
758              user    0m2.093s
759              sys     0m0.468s
760              
761              Case n=4555 Total possible nodes in thie state space tree is 2^4555-1
762                        Number of nodes placed in the priority queue:  45994
763 rizwank 1.14           Number of nodes examined/split:                45381
764              
765              real    1m5.247s
766              user    1m3.374s
767              sys     0m0.327s
768              after a presort. What about decsending sort?
769              
770              note, removing -g only kills a 1 second or something
771              
772              real    0m2.446s
773              user    0m2.186s
774              sys     0m0.203s
775              
776              with presort and early out
777 rizwank 1.15 
778              with sort and weight based item compare
779              
780              
781              with item based compare
782              real    0m2.676s
783              user    0m2.499s
784              sys     0m0.108s
785              
786              item based compare AND sort
787              real    0m2.543s
788              user    0m2.452s
789              sys     0m0.062s
790              
791 rizwank 1.1  		
792              		*/
793              

Rizwan Kassim
Powered by
ViewCVS 0.9.2