|
version 1.2, 2005/02/16 07:17:25
|
version 1.15, 2005/02/17 08:01:32
|
|
|
|
| |
#include<stdlib.h> |
| |
#include<iostream> |
| |
#include<fstream> |
| |
#include<string> |
| #include <queue> | #include <queue> |
| |
#include <stack> |
| |
#include <vector> |
| #include <stdio.h> | #include <stdio.h> |
| | |
| // As per specification, the project has to be able to grow to an |
using namespace std; |
| // arbitrary amount of items. MAX_ITEMS describes the size of the |
|
| // appropriate arrays and must be changed at compile time. |
//threading might be useful except for the fact that our target machine is likely to have a single processor |
| // (dynamically created arrays had their pointers corrupted when |
// what about task limiting from SEAS? |
| // their parent object was in the priority queue, so static sized |
// actually sparc machines on ugrad are multiple processor -- could I thread/fork the calculations? would overhead > savings |
| // arrays were used |
// 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 |
| |
// of course, vector<bool> packs 8 bools in a byte, arrays dont |
| |
|
| |
typedef long ITEM_MASS; |
| |
typedef long INDEX_TYPE; |
| | |
| #define MAX_ITEMS 55 |
|
| | |
| using namespace std; | using namespace std; |
| | |
|
|
|
| // * CLASS : item * | // * CLASS : item * |
| // * Container object with all the data for a particular item * | // * Container object with all the data for a particular item * |
| // ****************************************************************** | // ****************************************************************** |
| |
|
| |
//since items are no longer special in any way, I could actually just use a vector now! |
| |
// would this be any faster? |
| |
|
| class item { | class item { |
| public: | public: |
| float getRatio(); |
ITEM_MASS getWeight(); |
| unsigned short getWeight(); |
void setData(ITEM_MASS); |
| unsigned short getCost(); |
|
| unsigned short getNumber(); |
|
| void setData(unsigned short,unsigned short,unsigned short); |
|
| private: | private: |
| unsigned short weight; |
ITEM_MASS weight; |
| unsigned short cost; |
|
| float ratio; |
|
| unsigned short number; |
|
| }; | }; |
| | |
| // ****************************************************************** | // ****************************************************************** |
|
|
|
| void flagNext(); | void flagNext(); |
| void addCurItem(); | void addCurItem(); |
| bool doneItems(); | bool doneItems(); |
| float getBound(); |
ITEM_MASS getBound(); |
| bool checkItem(unsigned short); |
bool checkItem(INDEX_TYPE); |
| unsigned short getWeight(); |
ITEM_MASS getWeight(); |
| unsigned short getValue(); |
|
| private: | private: |
| void calcBound(); | void calcBound(); |
| bool inserted[MAX_ITEMS]; |
vector<bool> inserted; |
| unsigned short nextitem; |
// replace with a vector! this allows us to remove MAX_ITEMS without the fussyness of copying the |
| unsigned short cur_weight; |
// contents of a pointer etc like before! |
| unsigned short cur_value; |
// bool inserted[MAX_ITEMS]; |
| float upper_bound; |
INDEX_TYPE nextitem; |
| |
ITEM_MASS cur_weight; |
| |
ITEM_MASS upper_bound; |
| backpack *myBackpack; | backpack *myBackpack; |
| }; | }; |
| | |
|
|
|
| // ****************************************************************** | // ****************************************************************** |
| struct item_comparator { | struct item_comparator { |
| bool operator()( item left, item right ) const | bool operator()( item left, item right ) const |
| { return ( left.getRatio() < right.getRatio() ) ; } |
// { return ( left.getRatio() < right.getRatio() ) ; } |
| |
// { return ( left.getWeight() < right.getWeight() ); } |
| |
{return 0;} |
| |
// larger boxes are preferable to smaller boxes |
| |
// removes the need for sort at beginning. |
| |
// this actually massively increases the time cost for my sample set. defaulting to dumb sort |
| } ; | } ; |
| | |
| // ****************************************************************** | // ****************************************************************** |
|
|
|
| // ****************************************************************** | // ****************************************************************** |
| class backpack { | class backpack { |
| public: | public: |
| void initBackpack(unsigned short, unsigned short); |
void initBackpack(INDEX_TYPE, ITEM_MASS); |
| void putItem(unsigned short, unsigned short); |
void changeBackpack(INDEX_TYPE); |
| |
void putItem(ITEM_MASS);//, ITEM_MASS); |
| void store_item_array(); | void store_item_array(); |
| void branch_and_bound(); |
void branch_and_bound(int,ITEM_MASS); |
| unsigned short get_totalItems(); |
ITEM_MASS get_totalItems(); |
| unsigned short get_maxWeight(); |
ITEM_MASS get_maxWeight(); |
| item get_Item(unsigned short); |
item get_Item(INDEX_TYPE); |
| private: | private: |
| priority_queue< item, vector<item> , item_comparator> item_queue; | priority_queue< item, vector<item> , item_comparator> item_queue; |
| item *item_array; | item *item_array; |
| priority_queue< key, vector<key>, key_comparator> key_queue; | priority_queue< key, vector<key>, key_comparator> key_queue; |
| unsigned short totalItems; |
INDEX_TYPE totalItems; |
| unsigned short maxWeight; |
ITEM_MASS maxWeight; |
| long addnodeCount, worknodeCount; | long addnodeCount, worknodeCount; |
| }; | }; |
| | |
|
|
|
| this->myBackpack = theCaller; | this->myBackpack = theCaller; |
| this->nextitem=0; | this->nextitem=0; |
| this->cur_weight=0; | this->cur_weight=0; |
| this->cur_value=0; |
|
| this->calcBound(); | this->calcBound(); |
| } | } |
| | |
|
|
|
| // * as processed, then updates the bound. * | // * as processed, then updates the bound. * |
| // ****************************************************************** | // ****************************************************************** |
| void key::flagNext(){ | void key::flagNext(){ |
| this->inserted[this->nextitem]=0; |
// this->inserted[this->nextitem]= 0; |
| |
this->inserted.push_back(0); |
| nextitem++; | nextitem++; |
| this->calcBound(); | this->calcBound(); |
| } | } |
|
|
|
| // ****************************************************************** | // ****************************************************************** |
| void key::addCurItem(){ | void key::addCurItem(){ |
| nextitem--; | nextitem--; |
| this->inserted[this->nextitem]=1; |
this->inserted.push_back(1); |
| this->cur_value += (this->myBackpack->get_Item(this->nextitem)).getCost(); |
// this->inserted[this->nextitem]=1; |
| this->cur_weight += (this->myBackpack->get_Item(this->nextitem)).getWeight(); | this->cur_weight += (this->myBackpack->get_Item(this->nextitem)).getWeight(); |
| nextitem++; | nextitem++; |
| this->calcBound(); | this->calcBound(); |
|
|
|
| // * FUNCTION : getBound IN : CLASS key * | // * FUNCTION : getBound IN : CLASS key * |
| // * Returns the bound. * | // * Returns the bound. * |
| // ****************************************************************** | // ****************************************************************** |
| float key::getBound(){ |
ITEM_MASS key::getBound(){ |
| return this->upper_bound; | return this->upper_bound; |
| } | } |
| | |
|
|
|
| // * If the weight is over max_weight, set the bound to 0 * | // * If the weight is over max_weight, set the bound to 0 * |
| // ****************************************************************** | // ****************************************************************** |
| void key::calcBound(){ | void key::calcBound(){ |
| float temp; |
ITEM_MASS temp; |
| if (this->doneItems()) { | if (this->doneItems()) { |
| temp = 0; | temp = 0; |
| } | } |
| else { | else { |
| temp = (float)((this->myBackpack->get_maxWeight()) - cur_weight); |
temp = ((this->myBackpack->get_maxWeight()) - cur_weight); |
| temp = temp * (this->myBackpack->get_Item(this->nextitem)).getRatio(); |
|
| } | } |
| this->upper_bound = cur_value + temp; |
this->upper_bound = cur_weight + temp; |
| | |
| // What about if the bag is overloaded? | // What about if the bag is overloaded? |
| if (this->cur_weight > this->myBackpack->get_maxWeight()){ | if (this->cur_weight > this->myBackpack->get_maxWeight()){ |
|
|
|
| // * FUNCTION : checkItem IN : CLASS key * | // * FUNCTION : checkItem IN : CLASS key * |
| // * Checks if a given item is listed as inserted. * | // * Checks if a given item is listed as inserted. * |
| // ****************************************************************** | // ****************************************************************** |
| bool key::checkItem(unsigned short num) { |
bool key::checkItem(INDEX_TYPE num) { |
| return (this->inserted[num]); | return (this->inserted[num]); |
| } | } |
| | |
| // ****************************************************************** | // ****************************************************************** |
| // * FUNCTION : getValue IN : CLASS key * |
|
| // * Gets the Value of the current key. * |
|
| // ****************************************************************** |
|
| unsigned short key::getValue(){ |
|
| return this->cur_value; |
|
| } |
|
| |
|
| // ****************************************************************** |
|
| // * FUNCTION : getWeight IN : CLASS key * | // * FUNCTION : getWeight IN : CLASS key * |
| // * Gets the Weight of the current key. * | // * Gets the Weight of the current key. * |
| // ****************************************************************** | // ****************************************************************** |
| unsigned short key::getWeight(){ |
ITEM_MASS key::getWeight(){ |
| return this->cur_weight; | return this->cur_weight; |
| } | } |
| | |
| // ****************************************************************** | // ****************************************************************** |
| // * FUNCTION : getRatio IN : CLASS item * |
|
| // * Gets the Ratio for the current item. * |
|
| // ****************************************************************** |
|
| float item::getRatio(){ |
|
| return ratio; |
|
| } |
|
| |
|
| // ****************************************************************** |
|
| // * FUNCTION : getWeight IN : CLASS item * | // * FUNCTION : getWeight IN : CLASS item * |
| // * Gets the Weight of the current item. * | // * Gets the Weight of the current item. * |
| // ****************************************************************** | // ****************************************************************** |
| unsigned short item::getWeight(){ |
ITEM_MASS item::getWeight(){ |
| return this->weight; | return this->weight; |
| } | } |
| | |
| // ****************************************************************** |
|
| // * FUNCTION : getCost IN : CLASS item * |
|
| // * Gets the Value of the current item. * |
|
| // ****************************************************************** |
|
| unsigned short item::getCost(){ |
|
| return this->cost; |
|
| } |
|
| |
|
| // ****************************************************************** |
|
| // * FUNCTION : getNumber IN : CLASS item * |
|
| // * Gets the Index of the current item. * |
|
| // ****************************************************************** |
|
| unsigned short item::getNumber(){ |
|
| return this->number; |
|
| } |
|
| | |
| // ****************************************************************** | // ****************************************************************** |
| // * FUNCTION : setData IN : CLASS item * | // * FUNCTION : setData IN : CLASS item * |
| // * Sets all the data for an item. * | // * Sets all the data for an item. * |
| // ****************************************************************** | // ****************************************************************** |
| void item::setData(unsigned short weightage, unsigned short costage, unsigned short numerage){ |
void item::setData(ITEM_MASS weightage){ //, ITEM_MASS costage, ITEM_MASS numerage){ |
| this->cost = costage; |
// this->cost = weightage; //costage; |
| this->weight = weightage; | this->weight = weightage; |
| this->ratio = ( (float)(cost)/(float)(weight) ); |
// this->ratio = ( (float)(cost)/(float)(weight) ); |
| this->number = numerage; |
// this->ratio = 1; //ratio = 1 |
| |
// this->number = numerage; |
| } | } |
| | |
| | |
|
|
|
| // * FUNCTION : initBackpack IN : CLASS backpack * | // * FUNCTION : initBackpack IN : CLASS backpack * |
| // * Initalizes the backpack values and creates the item array * | // * Initalizes the backpack values and creates the item array * |
| // ****************************************************************** | // ****************************************************************** |
| void backpack::initBackpack(unsigned short total, unsigned short max){ |
void backpack::initBackpack(INDEX_TYPE total, ITEM_MASS max){ |
| this->totalItems = total; |
|
| this->maxWeight = max; | this->maxWeight = max; |
| |
this->totalItems = total; |
| item_array = new item[total]; | item_array = new item[total]; |
| worknodeCount = 0; | worknodeCount = 0; |
| addnodeCount = 0; | addnodeCount = 0; |
| } | } |
| | |
| |
|
| |
|
| // ****************************************************************** | // ****************************************************************** |
| // * FUNCTION : putItem IN : CLASS backpack * | // * FUNCTION : putItem IN : CLASS backpack * |
| // * Creates an item and places it into the priority queue * | // * Creates an item and places it into the priority queue * |
| // ****************************************************************** | // ****************************************************************** |
| void backpack::putItem(unsigned short weight, unsigned short cost){ |
void backpack::putItem(ITEM_MASS weight){ //, ITEM_MASS cost){ |
| item temp_item; | item temp_item; |
| temp_item.setData(weight,cost,(int)(this->item_queue.size())+1); |
temp_item.setData(weight);//,cost);//,(int)(this->item_queue.size())+1); // sometimes this starts at 2000? |
| this->item_queue.push(temp_item); | this->item_queue.push(temp_item); |
| } | } |
| | |
|
|
|
| // * FUNCTION : get_totalItems IN : CLASS backpack * | // * FUNCTION : get_totalItems IN : CLASS backpack * |
| // * Returns the number of items for consideration. * | // * Returns the number of items for consideration. * |
| // ****************************************************************** | // ****************************************************************** |
| unsigned short backpack::get_totalItems(){ |
ITEM_MASS backpack::get_totalItems(){ |
| return this->totalItems; | return this->totalItems; |
| } | } |
| | |
|
|
|
| // * FUNCTION : get_maxWeight IN : CLASS backpack * | // * FUNCTION : get_maxWeight IN : CLASS backpack * |
| // * Returns the maximum weight for this backpack. * | // * Returns the maximum weight for this backpack. * |
| // ****************************************************************** | // ****************************************************************** |
| unsigned short backpack::get_maxWeight(){ |
ITEM_MASS backpack::get_maxWeight(){ |
| return this->maxWeight; | return this->maxWeight; |
| } | } |
| | |
|
|
|
| // * FUNCTION : get_Item IN : CLASS backpack * | // * FUNCTION : get_Item IN : CLASS backpack * |
| // * Returns a particular item from the item array * | // * Returns a particular item from the item array * |
| // ****************************************************************** | // ****************************************************************** |
| item backpack::get_Item(unsigned short index){ |
item backpack::get_Item(INDEX_TYPE index){ |
| return ( this->item_array[index] ); | return ( this->item_array[index] ); |
| } | } |
| | |
|
|
|
| // * possible solution for this knapsack. * | // * possible solution for this knapsack. * |
| // * Fetch all the information and print it out. * | // * Fetch all the information and print it out. * |
| // ****************************************************************** | // ****************************************************************** |
| void backpack::branch_and_bound(){ |
void backpack::branch_and_bound(int DEBUG_MODE, ITEM_MASS targetvalue){ |
| key temp_key; | key temp_key; |
| | |
| temp_key.initKey(this); | temp_key.initKey(this); |
|
|
|
| this->addnodeCount++; | this->addnodeCount++; |
| | |
| bool onwards = 1; | bool onwards = 1; |
| |
|
| do | do |
| { | { |
| temp_key = key_queue.top(); | temp_key = key_queue.top(); |
| this->key_queue.pop(); | this->key_queue.pop(); |
| |
/*Early skip here -- MASSIVE speed improvements */ |
| |
if ( temp_key.getWeight() == targetvalue ) { |
| |
//printf("Early value acquired! %d\n",temp_key.getWeight() ); |
| |
goto early; // yes thats a go to. Its the only way to leave and keep the context right. I know its horrible |
| |
} |
| |
// printf("reached %d\n",temp_key.getWeight()); |
| if ( temp_key.doneItems() ) { | if ( temp_key.doneItems() ) { |
| onwards = 0; | onwards = 0; |
| } | } |
| else { | else { |
| this->worknodeCount++; |
// this->worknodeCount++; |
| temp_key.flagNext(); | temp_key.flagNext(); |
| this->key_queue.push(temp_key); | this->key_queue.push(temp_key); |
| this->addnodeCount++; |
// this->addnodeCount++; |
| |
|
| |
// try this --- compare quicksorted before and after because of greedy grabbing largest |
| |
//should find other comparator for weight with sub data like ... pct done |
| |
|
| temp_key.addCurItem(); | temp_key.addCurItem(); |
| if (temp_key.getBound() != 0){ |
if (temp_key.getBound() != 0){ //insert only if active. |
| this->key_queue.push(temp_key); | this->key_queue.push(temp_key); |
| this->addnodeCount++; |
// this->addnodeCount++; |
| } | } |
| } | } |
| |
// commenting out worknode trackerincreases speed by 3% |
| } | } |
| while (onwards); | while (onwards); |
| | |
| |
early: if (DEBUG_MODE) { |
| |
|
| printf("Case n=%2d Total possible nodes in thie state space tree is 2^%2d-1\n",this->totalItems,this->totalItems); | printf("Case n=%2d Total possible nodes in thie state space tree is 2^%2d-1\n",this->totalItems,this->totalItems); |
| printf(" Number of nodes placed in the priority queue: %6d\n",this->addnodeCount); |
printf(" DISABLED Number of nodes placed in the priority queue: %6d\n",this->addnodeCount); |
| printf(" Number of nodes examined/split: %6d\n",this->worknodeCount); |
printf(" DISABLED Number of nodes examined/split: %6d\n",this->worknodeCount); |
| |
} |
| |
|
| printf("\nObjects Chosen \n"); |
|
| | |
| printf(" Objects Weights Values\n"); |
if ( temp_key.getWeight() == targetvalue ) { |
| int totalitemsinserted = 0; | int totalitemsinserted = 0; |
| |
int first=1; |
| for (int i = 0; this->totalItems > i; i++) { | for (int i = 0; this->totalItems > i; i++) { |
| if ( temp_key.checkItem(i) ) { | if ( temp_key.checkItem(i) ) { |
| printf(" %2d %2d %2d\n", this->item_array[i].getNumber(), this->item_array[i].getWeight(), this->item_array[i].getCost()); |
if (first==0) { printf(","); } |
| totalitemsinserted++; |
else {first = 0;} // there has GOT to be a better way! |
| |
printf("%d", this->item_array[i].getWeight()); |
| |
} |
| |
} |
| |
} |
| |
else { printf("CANNOT FILL PALLET\n"); } |
| |
} |
| |
|
| |
void super_increase_algo ( vector<ITEM_MASS> inventory, ITEM_MASS target_value , int DEBUG_MODE ) { |
| |
stack<ITEM_MASS> packages_to_load; |
| |
INDEX_TYPE size_inventory = inventory.size(); |
| |
|
| |
if (DEBUG_MODE) { |
| |
printf("Extracting values, highest to lowest, doing reduction from index %d\n",size_inventory); |
| |
} |
| |
for ( INDEX_TYPE store_index=size_inventory-1; store_index>=0;store_index-- ) { |
| |
if (DEBUG_MODE) { |
| |
printf("value %d, is it smaller than %d? If so, subtract and store.\n",inventory[store_index],target_value); |
| |
} |
| |
if ( inventory[store_index] <= target_value ) { |
| |
target_value = target_value - inventory[store_index]; |
| |
packages_to_load.push(inventory[store_index]); |
| } | } |
| } | } |
| printf("======================================================\n"); |
if ( target_value == 0 ) { |
| printf("Totals: %2d %2d %2d\n",totalitemsinserted, temp_key.getWeight(), temp_key.getValue()); |
int first = 1; |
| printf("Ratio : %2.5f\n", ((float)temp_key.getValue()/(float)temp_key.getWeight())); |
while ( ! packages_to_load.empty() ) { |
| |
if (first==0) { printf(","); } |
| |
else {first = 0;} // there has GOT to be a better way! |
| |
printf("%d",packages_to_load.top()); |
| |
packages_to_load.pop(); |
| |
} |
| |
printf("\n"); |
| |
} |
| |
else { printf("CANNOT FILL PALLET\n"); } |
| } | } |
| | |
| |
|
| |
void syntaxmsg(){ |
| |
printf("Usage:\n"); |
| |
printf("<program name> <input filename> <D/d>\n"); |
| |
printf("input contains a series of integers [A], comma delimited,\n\t followed by a CR and an int [B]\n"); |
| |
printf("program outputs a comma delimited list of elements of A that sum to B,\n\t or CANNOT FILL PALLET\n"); |
| |
printf("Program written for the UCLA ACM Feb 2005 Coding Competition\n"); |
| |
printf("Dervied from previous academic work written by the author\n(C) 2002-2005 Rizwan Kassim\n"); |
| |
printf("If the second argument is a D or d, verbose debugging mode will be enabled\n\n"); |
| |
return; |
| |
} |
| |
|
| |
|
| |
ITEM_MASS masscomp (const void * a, const void * b) |
| |
{ |
| |
return ( *(ITEM_MASS*)a - *(ITEM_MASS*)b ); |
| |
} |
| |
|
| |
|
| // ****************************************************************** | // ****************************************************************** |
| // * FUNCTION : main * | // * FUNCTION : main * |
| // * Initalizes the backpack and the items inside. * | // * Initalizes the backpack and the items inside. * |
|
|
|
| int main(int argc, char *argv[]) | int main(int argc, char *argv[]) |
| { | { |
| item temp_item; | item temp_item; |
| printf("CS331_Project 4, by Rizwan Kassim.\n"); |
int DEBUG_MODE = 0; |
| printf("Version 3\n"); |
|
| printf("All compiled / source code are (C) Rizwan Kassim 2003\n\n"); |
|
| | |
| |
if ( argc < 2 ) { syntaxmsg(); return 2;} |
| |
if ( argc > 4 ) { syntaxmsg(); return 3;} |
| |
if ( argc == 3 ) { |
| |
if ( argv[2][0] == 'D' || argv[2][0] == 'd' ) { |
| |
printf("Debug switch caught, outputing debug messages\n"); |
| |
DEBUG_MODE =1; |
| |
} else { syntaxmsg(); return 4;} |
| |
} |
| | |
| printf("============================ KNAPSACK ONE ================================\n"); |
if (DEBUG_MODE) { |
| backpack knapsackOne; |
printf("Entry into UCLA ACM Feb. 2005 Coding Competition\n"); |
| |
printf("Based on code developed (myself) for CS331 Project 4 at CSU Pomona\n"); |
| |
printf("Version 4\n"); |
| |
printf("All compiled / source code are (C) Rizwan Kassim 2005\n\n"); |
| |
} |
| | |
| knapsackOne.initBackpack(25,200); // 5 total items, 17 total weight |
ifstream inputfs; |
| knapsackOne.packitem(70,70); |
inputfs.open (argv[1]); |
| knapsackOne.packitem(76,76); |
if (!inputfs.is_open()) |
| knapsackOne.packitem(55,55); |
{ printf("File open of %s failed!\n", argv[1]); |
| knapsackOne.packitem(17,17); |
syntaxmsg(); |
| knapsackOne.packitem(70,70); |
return 1; } |
| knapsackOne.packitem(77,77); |
if (DEBUG_MODE) { |
| knapsackOne.packitem(52,52); |
printf("File %s Open!\n",argv[1]); |
| knapsackOne.packitem(81,81); |
} |
| knapsackOne.packitem(11,11); |
|
| knapsackOne.packitem(31,31); |
INDEX_TYPE length; |
| knapsackOne.packitem(57,57); |
inputfs.seekg (0, ios::end); |
| knapsackOne.packitem(47,47); |
length = inputfs.tellg(); |
| knapsackOne.packitem(93,93); |
inputfs.seekg (0, ios::beg); |
| knapsackOne.packitem(53,53); |
|
| knapsackOne.packitem(83,83); |
|
| knapsackOne.packitem(33,33); |
|
| knapsackOne.packitem(1,1); |
|
| knapsackOne.packitem(59,59); |
|
| knapsackOne.packitem(29,29); |
|
| knapsackOne.packitem(33,33); |
|
| knapsackOne.packitem(78,78); |
|
| knapsackOne.packitem(79,79); |
|
| knapsackOne.packitem(37,37); |
|
| knapsackOne.packitem(26,26); |
|
| knapsackOne.packitem(83,83); |
|
| knapsackOne.store_item_array(); |
|
| | |
| |
char * read_buffer = (char *) malloc (length); |
| |
vector<ITEM_MASS> inventory; |
| |
// could use stack instead of array --- doesn't require malloc, more 'safe' avoids overflows, esp if |
| |
// input file is funky --- its better software engineering, but its slower. Given that this is a pretty |
| |
// small system, I'll stick with the array --- oh even better -- a vector! |
| |
//http://theory.stanford.edu/~amitp/rants/c++-vs-c/ Vector speed sorting is optimized by using vector! |
| |
inputfs.getline (read_buffer, length-1); |
| | |
| for ( int i = 0; knapsackOne.get_totalItems() > i; i++){ |
char * theToken; INDEX_TYPE index = 0; |
| temp_item=knapsackOne.get_Item(i); |
theToken=strtok(read_buffer,","); |
| printf("Item Number %2d : %2d cost for %2d weight at ratio %2.3f\n", temp_item.getNumber(), temp_item.getCost(), temp_item.getWeight(), temp_item.getRatio()); |
// assume 1+ items |
| |
while ( theToken != NULL ) { |
| |
//printf("tokendebug %d %f\n",theToken,theToken); |
| |
inventory.push_back(atol(theToken)); |
| |
//printf("index %d, token %s, value %d\n",index,theToken,inventory[index]); |
| |
index++; |
| |
theToken = strtok (NULL,","); |
| } | } |
| printf("\n"); |
|
| | |
| knapsackOne.branch_and_bound(); |
|
| |
int SUPER_MODE = 0; |
| |
if (inventory[0]==1) { SUPER_MODE=1;} |
| |
|
| |
if (DEBUG_MODE) { |
| |
printf("Line 1 read - %d products from warehouse\n", inventory.size()); |
| |
if (SUPER_MODE) printf("Working in Superincreasing mode!\n"); |
| |
} |
| |
|
| |
// sort (inventory.begin(), inventory.end(),std::greater<ITEM_MASS>() ); |
| |
// sort (inventory.begin(), inventory.end()); // most efficient, uses largest boxes inherently |
| |
|
| |
// NEED TRY/CATCH error handling for possible segfault locations |
| |
inputfs.getline (read_buffer, length-1); |
| |
ITEM_MASS palette_size=atol(read_buffer); |
| |
|
| |
if (DEBUG_MODE) { |
| |
printf("Line 2 read - %d weight units can fit onto palette\n",palette_size); |
| |
} |
| |
|
| |
inputfs.close(); |
| |
free(read_buffer); |
| |
|
| |
|
| |
// I could use a class to extrapolate out the file loading function like my 499 project.... |
| |
|
| |
|
| |
if (SUPER_MODE) { |
| |
super_increase_algo (inventory, palette_size , DEBUG_MODE ); |
| |
return 0; |
| |
} |
| |
|
| |
// filter out oversizes BEFORE we insert them above, therefore making life complicated |
| |
|
| |
vector<ITEM_MASS>::iterator itInventory; |
| |
|
| |
// printf("inventory before %d\n",inventory.size()); |
| |
for(itInventory = inventory.begin(); itInventory != inventory.end(); itInventory++) { |
| |
if (*itInventory > palette_size ) { |
| |
// printf("%d removing at , left %d!\n",*itInventory,inventory.size()); |
| |
inventory.erase(itInventory); |
| |
itInventory--; |
| |
// printf("%d removed at %d, left!\n",*itInventory,inventory.size()); |
| |
// remove elements that are too large. its a n increase here, but >>n increase if done later |
| |
} |
| |
} |
| |
|
| |
backpack knapsackOne; |
| |
|
| |
knapsackOne.initBackpack(inventory.size(),palette_size); |
| |
if (DEBUG_MODE) { |
| |
printf("init %d, %d\n",inventory.size(),palette_size); |
| |
} |
| |
|
| |
for(itInventory = inventory.begin(); itInventory != inventory.end(); itInventory++) { |
| |
knapsackOne.putItem(*itInventory); |
| |
// if (DEBUG_MODE) { |
| |
// printf("insert %d\n",*itInventory); |
| |
// } |
| |
} |
| |
|
| |
knapsackOne.store_item_array(); |
| |
inventory.clear(); |
| |
|
| |
knapsackOne.branch_and_bound(DEBUG_MODE,palette_size); |
| | |
| printf("\n"); | printf("\n"); |
| } | } |
| | |
| | |
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| /* | /* |
| Modifications to the original branch-and-bound algorithim/approach | Modifications to the original branch-and-bound algorithim/approach |
| | |
|
|
|
| | |
| And lets try with a random set of 25 numbers! | And lets try with a random set of 25 numbers! |
| 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 | 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 |
| |
Chose: |
| |
1 70 70 |
| |
3 55 55 |
| |
24 26 26 |
| |
23 37 37 |
| |
17 1 1 |
| |
9 11 11 |
| |
2^25-1 worst case, 142 nodes, 115 split! |
| |
real 0m0.036s |
| |
user 0m0.030s |
| |
sys 0m0.030s |
| |
|
| | |
| | |
| | |
| then 50: | then 50: |
| 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 | 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 |
| |
2^50 worst case, 1826 nodes, 1443 splits |
| |
real 0m0.044s |
| |
user 0m0.062s |
| |
sys 0m0.000s |
| |
|
| |
|
| |
Now, lets really ramp it up so that we can see optimzation effects |
| |
n=2500! won't even care to list the numbers, no point! |
| |
|
| |
Wait, we exceeded 3 minutes there (our weight size was just a guess, btw, might not actually ahve a value) |
| |
Oh, our memory bound was maxed out so it hit a loop ... it actually completed in less than a sec! God bless my processor :) |
| |
Lets bump it up to 5k, |
| |
|
| |
Case n=5000 Total possible nodes in thie state space tree is 2^5000-1 |
| |
Number of nodes placed in the priority queue: 35037 |
| |
Number of nodes examined/split: 34942 |
| |
|
| |
real 0m2.810s |
| |
user 0m1.843s |
| |
sys 0m0.062s |
| |
|
| |
|
| |
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! |
| |
|
| |
must do 1 - |
| |
move all the ITEM_MASSs to (other) |
| |
the ITEM_MASSs are now ITEM_TYPE, a def earlier on (we could have done typedef here too, of course) |
| |
real 0m2.928s |
| |
user 0m1.999s |
| |
sys 0m0.061s |
| |
Slight increase. |
| |
|
| |
Bad things happen when we try to make it into floats, I just tired. floats can't be [] contents for an array ;p |
| |
Doing unsigned long for now. |
| |
goal 1 = stop ratio calculation and comparisons if at all possible! |
| |
real time shot up! |
| |
real 0m3.994s |
| |
user 0m2.390s |
| |
sys 0m0.046s |
| |
|
| |
(that being said, timse don't seem to be consistent. CVS is storing our versions, lets plow on) |
| |
|
| |
remove the comparator in the structcomparator |
| |
real 0m2.830s |
| |
user 0m2.030s |
| |
sys 0m0.015s |
| |
|
| |
remove the printout of the items as inserted |
| |
real 0m1.423s |
| |
user 0m1.436s |
| |
sys 0m0.015s |
| |
|
| |
remove the tracking of the item "number", we don't need to deal with it with this project. |
| |
|
| |
after moved all unsigned ints to typedefs, |
| |
typedef float ITEM_MASS; |
| |
typedef long INDEX_TYPE; |
| |
|
| |
and modified the printfs to handle floating ! |
| |
|
| |
real 0m1.591s |
| |
user 0m1.562s |
| |
sys 0m0.000s |
| |
|
| |
inserting a float does : |
| |
|
| |
acm2.cpp: In function `int main(int, char**)': |
| |
acm2.cpp:410: error: no matching function for call to `backpack::putItem( |
| |
double, int, int)' |
| |
acm2.cpp:279: error: candidates are: void backpack::putItem(float, float) |
| |
make: *** [acm2] Error 1 |
| |
|
| |
(and it locks up if we have a decimal in seeked value) |
| |
|
| |
ok we move onwards to remove weight,value calls and replace them with just weight |
| |
we also use notepad/sed to remove half the sample knapsack calls |
| |
we realize in doing this that we've actually got 7009 elements! modifiying appropraite values! |
| |
|
| |
real 0m2.627s |
| |
user 0m2.624s |
| |
sys 0m0.000s |
| |
|
| |
but now it uses all 17. |
| |
|
| |
|
| |
Lets try an appropriately high value instead of the 50000ish we're using now. Lets say, we want ... |
| |
600 elements of 7000, at avg value of 5000 3000000ish? |
| |
|
| |
Case n=6998 Total possible nodes in thie state space tree is 2^6998-1 |
| |
Number of nodes placed in the priority queue: 70797 |
| |
Number of nodes examined/split: 69811 |
| |
|
| |
Totals: 114 509283.00 509283.00 |
| |
|
| |
then... |
| |
|
| |
============================ KNAPSACK ONE ================================ |
| |
Case n=6998 Total possible nodes in thie state space tree is 2^6998-1 |
| |
Number of nodes placed in the priority queue: 108848 |
| |
Number of nodes examined/split: 96391 |
| |
|
| |
Totals: 1002 5091283.00 5091283.00 |
| |
|
| |
|
| |
real 0m9.526s |
| |
user 0m9.249s |
| |
sys 0m0.203s |
| |
|
| |
|
| |
I'm actually pretty happy with this. We havent tested a few conditions, but its time we got the file loading routine in |
| |
|
| |
|
| |
todo |
| |
1) when it doesnt work |
| |
2) when its already reached stop |
| |
3) float |
| |
|
| |
For superincreasing sets, its INCREDIBLY easy to do |
| |
Sort it. |
| |
if (current value < pallete size), palletsize-current value, current_value on board. |
| |
repeat until end |
| |
|
| |
|
| |
|
| |
=== loading file now |
| |
make input float ok |
| |
|
| |
reverted to base type of non float --- making the stored value float did badthings to atoi / atof (they didnt work) |
| |
|
| |
|
| |
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? |
| |
|
| |
goal 1 - lets remove the double call to the creator function, weight=value ratio=1 |
| |
|
| |
|
| |
large set time : |
| |
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 |
| |
|
| |
real 1m14.327s |
| |
user 1m11.530s |
| |
sys 0m0.421s |
| |
|
| |
with goto removed. |
| |
|
| |
|
| |
largeset time with early leave! |
| |
Early value acquired! 13273 |
| |
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 |
| |
|
| |
real 0m2.594s |
| |
user 0m2.093s |
| |
sys 0m0.468s |
| |
|
| |
Case n=4555 Total possible nodes in thie state space tree is 2^4555-1 |
| |
Number of nodes placed in the priority queue: 45994 |
| |
Number of nodes examined/split: 45381 |
| |
|
| |
real 1m5.247s |
| |
user 1m3.374s |
| |
sys 0m0.327s |
| |
after a presort. What about decsending sort? |
| |
|
| |
note, removing -g only kills a 1 second or something |
| |
|
| |
real 0m2.446s |
| |
user 0m2.186s |
| |
sys 0m0.203s |
| |
|
| |
with presort and early out |
| |
|
| |
with sort and weight based item compare |
| |
|
| | |
| |
with item based compare |
| |
real 0m2.676s |
| |
user 0m2.499s |
| |
sys 0m0.108s |
| | |
| |
item based compare AND sort |
| |
real 0m2.543s |
| |
user 0m2.452s |
| |
sys 0m0.062s |
| | |
| | |
| */ | */ |