Пример #1
0
/**
 * Calculates the value/cost ratio for each object
 * And stores the ratios in a vector
 * TODO sort values to improve runtime
 * @param k the knapsack to use
 */
void calculateValueCostRatios(knapsack &k) {
	for (int i = 0; i < k.getNumObjects(); i++)
	{
		valueCostRatio.insert(valueCostRatio.begin() + i,
				(k.getValue(i) / (double)k.getCost(i)));
	}
}
knapsack::knapsack(const knapsack &k)
// Knapsack copy constructor
{
   numObjects = k.getNumObjects();
   costBound = k.getCostBound();

   value.resize(numObjects);
   cost.resize(numObjects);
   index.resize(numObjects);
   selected.resize(numObjects);

   for (int i = 0; i < numObjects; i++)
   {
      setValue(i,k.getValue(i));
      setCost(i,k.getCost(i));
      setIndex(i,k.getIndex(i));

      if (k.isSelected(i))
	 select(i);
      else
	 unSelect(i);
   }

   setNum(k.getNum());
   currentValue = k.getCurrentValue();
   currentCost = k.getCurrentCost();
}
Пример #3
0
knapsack greedyKnapsack(vector<pair<double,int>> sortedSack, knapsack sack)
{
	int sackIndex;

	// outer for loop is iterating through sortedSack ratios
	// look for highest ratio item
	for (int i = 0; i < sack.getNumObjects(); i++)
	{
		// use second value of sorted sack pair as index
		sackIndex = sortedSack.at(i).second;

		//get ratio for specific sack(sackIndex)
		double ratioKnap;
		double valKnap = sack.getValue(sackIndex);
		double costKnap = sack.getCost(sackIndex);
		ratioKnap = valKnap / costKnap;

		if (sack.getCost() + sack.getCost(sackIndex) <= sack.getCostLimit())
		{
			sack.select(sackIndex);
		}
	}

	for (int k = 0; k < sack.getNumObjects(); k++)
	{
		cout<<sack.isSelected(k)<<endl;
	}

	return sack;
}
Пример #4
0
/**
 * Uses a greedy algorithm to find the best solution
 * @param k the knapsack to use
 * @param t the time limit
 */
void greedySolve(knapsack &k)
{
	calculateValueCostRatios(k);
	while (k.getCost() < k.getCostLimit()) {
		checkTimeLimit();
		int best = getBestObject(k);
		if (best == -1)
			break;
		k.select(best);
		valueCostRatio[best] = 0;
	}
}
Пример #5
0
/**
 * Selects the current best object to select
 * @param k the knapsack to use
 */
int getBestObject(knapsack &k) {
	int best = -1;
	for (int i = 0; i < k.getNumObjects(); i++)
	{
		if (best == -1 || valueCostRatio[i] > valueCostRatio[best])
		{
			if (valueCostRatio[i] > 0 && k.getCost(i) <= (k.getCostLimit() - k.getCost()))
			{
				best = i;
			}
		}
	}
	return best;
}
double greedyKnapsack(knapsack &k){
	MaxHeap<float, int>* heap = new MaxHeap<float, int>(&compare);
	for(int counter = 0; counter < k.getNumObjects(); counter++){
		double key = (double) k.getValue(counter) / k.getCost(counter);
		heap->add(key, counter);
	}
	while(! heap->empty()){
		int next = heap->extractMaxHeapMaximum();
		if(k.getCost(next) + k.getCurrentCost() <= k.getCostBound()){
			k.select(next);
		}
	}
	return k.getCurrentValue();
}
void exhaustiveKnapsack(knapsack sack, int timeLimit)
{
	// Get start time to be used in while loop
	time_t startTime;
	time(&startTime);


	// a while loop that expires when time limit is complete by checking difference of 
	// start time and current time at every loop
	while (true)
	{
		// Get current time and stop when greater than input time limit
		time_t newTime;
		time(&newTime);
		if (difftime(newTime, startTime) > timeLimit)
		{
			cout << "Time limit expired";
			break;
		}


		// Put main code here

		// Update current weight in sack every iteration of while loop
		int itemsSelected = 0;
		int currentWeight = 0;
		for (int i = 0; i < sack.getNumObjects(); i++)
		{
			itemsSelected++;
			currentWeight = sack.getCost(i) + currentWeight;
		}

		// Create random index to put into sack
		srand(time(NULL));
		int randNum = rand() % sack.getNumObjects();
		// if item isn't selected, and there is enough space, then select item
		if ((sack.isSelected(randNum) == false) && sack.getCost(randNum) + currentWeight <= sack.getCostLimit())
		{
			sack.select(randNum);
		}
		// Need an exit case where there is no more items that can fit in the sack
		else if (sack.getCost(randNum) + currentWeight > sack.getCostLimit())
		{
			// need to record sack weight and value and items when this happens (and there are 
			// no more items that can legally be added)
		}
		

	}
}
Пример #8
0
// sort all items in order of value/weight ratio
// and store the ratios in the index at which they exist in knapsack
vector<pair<double, int>> sortItems(knapsack sack)
{
	vector<pair<double, int>> ratios;

	for (int i = 0; i < sack.getNumObjects(); i++)
	{
		//cout << "sack.getValue(" << i << ")" << " = " << sack.getValue(i) << endl;
		//cout << "sack.getValue(" << i << ")" << " = " << sack.getCost(i) << endl;
		double ratio;
		double val = sack.getValue(i);
		double cost = sack.getCost(i);
		ratio = val / cost;
		//cout << "Ratio: " << ratio;
		//cout << "Pushing " << ratio << " to index " << i << endl;
		pair <double, int> ratInd; // ratio + index
		ratInd.first = ratio;
		ratInd.second = i;
		ratios.push_back(ratInd);
		//cout << endl << endl << endl;
	}

	// this preserves the original ratios vector just in case (may remove it later)
	vector<pair<double,int>> sortedRatios = ratios;

	sort(sortedRatios.begin(), sortedRatios.end());
	reverse(sortedRatios.begin(), sortedRatios.end());

	/*
	for (int i = 0; i < ratios.size(); i++)
	{
		//cout << "Ratio: " << sortedRatios.at(i) << " at index " << i << endl;
		//cout << "" << sortedRatios.at(i) << endl;
	}*/
	cin.get();
	return sortedRatios;
}
void branchAndBound(knapsack &k, int maxTime)
// Implement a Branch and Bound search for an optimal solution.
// Searches for the best decision for objects n and greater, as long
// as more than maxTime seconds have not elapsed.  Tries
// to keep or not keep object n, and then iterates to n+1.  Stores
// the best solution found so far in bestSolution.
{
	deque<knapsack> problem;

   clock_t startTime = clock();


   knapsack bestSolution(k);
   knapsack pessimisticBound(k);
   greedyKnapsack(pessimisticBound);
   float bestValue = pessimisticBound.getCurrentValue();

   // Initially, decisions have not been made about any objects,
   // so set num = 0.
   k.setNum(0);

   // Add the empty knapsack subproblem to the list
   problem.push_back(k);
   // Branch and Bound search goes here
   while(! problem.empty() && ((float)clock()-(float)startTime)/CLOCKS_PER_SEC < maxTime){
	   knapsack next = problem.front();problem.pop_front();
	   if(next.getCurrentValue() > bestSolution.getCurrentValue()){
		   bestSolution = next;
		   if(bestSolution.getCurrentValue() > bestValue)
			   bestValue = bestSolution.getCurrentValue();
	   }
	   knapsack k1(next);
	   k1.select(k1.getNum());
	   k1.setNum(k1.getNum() + 1);
	   if(k1.getCurrentCost() <= k1.getCostBound() && k1.bound() > bestValue && k1.getNum() < k1.getNumObjects()){
		   problem.push_back(k1);
	   }
	   knapsack k2(next);
	   k2.setNum(k2.getNum() + 1);
	   if(k2.bound() > bestValue && k2.getNum() < k2.getNumObjects()){
		   problem.push_back(k2);
	   }
    }
   cout << "Best value found: " << bestSolution.getCurrentValue() << endl;
   cout << bestSolution;
}
Пример #10
0
/**
 * @param k knapsack to find a solution for
 * @return new knapsack with a random solution
 */
knapsack randomSolution(knapsack &k)
{
	int i = 0;
	while (checkValid(k) && i < k.getNumObjects())
	{
		int random = rand() % 2;
		if (random == 1 && (k.getCost() + k.getCost(i)) < k.getCostLimit())
			k.select(i);
		else
			k.unSelect(i);
		i++;
	}
	return k;
}
void printSolution(knapsack &k, string filename)
// Prints out the solution.
{
	ofstream myfile;
	myfile.open (filename.c_str());
	myfile << "------------------------------------------------" << endl;

	myfile << "Total value: " << k.getCurrentValue() << endl;
	myfile << "Total cost: " << k.getCurrentCost() << endl << endl;

   // Print out objects in the solution
   for (int i = 0; i < k.getNumObjects(); i++)
      if (k.isSelected(i))
    	  myfile << i << "  " << k.getValue(i) << " " << k.getCost(i) << endl;

   myfile << endl;
   myfile.close();
}
Пример #12
0
/**
 * Finds a local optimum and returns the result
 *
 * @param k knapsack to find local optimum for
 * @param int 2-opt or 3-opt
 * @return new knapsack  with a local opt solution
 */
knapsack localOptimum(knapsack &k, int opt)
{
	knapsack original(k);
	deque<knapsack> problem;
	knapsack bestFound = knapsack(k);
	try
	{
		for (int l = 0; l < k.getNumObjects() - 1; l++)
		{
			k = knapsack(original);
			if (!k.isSelected(l))
				continue;
			k.unSelect(l);
			for (int m = l; m < k.getNumObjects() - 1; m++)
			{
				if (!k.isSelected(m))
					continue;
				k.unSelect(m);
				if (opt == 3)
				{
					for (int n = m; n < k.getNumObjects() - 1; n++)
					{
						if (!k.isSelected(n))
							continue;
						k.unSelect(n);
						problem.push_front(knapsack(k));
					}
				}
				else
					problem.push_front(knapsack(k));
			}
		}
		while(problem.size() > 0)
		{
			checkTimeLimit();
			knapsack current = problem.front();
			problem.pop_front();
			deque<knapsack> solution;
			solution.push_front(knapsack(current));
			int currentIndex = 0;
			while(solution.size() > 0)
			{
				knapsack currentSolution = solution.front();
				solution.pop_front();
				if (currentSolution.getValue() > bestFound.getValue())
				{
					bestFound = knapsack(currentSolution);
				}
				if (currentIndex < currentSolution.getNumObjects() - 1)
				{
					if (!currentSolution.isSelected(currentIndex) &&
							(currentSolution.getCost() + currentSolution.getCost(currentIndex)) < currentSolution.getCostLimit())
					{
						currentSolution.select(currentIndex);
						solution.push_front(knapsack(currentSolution));
					}
					currentIndex++;
				}
			}
		}
		return bestFound;

	}
	catch (baseException &ex)
	{
		cout << ex.what() << endl;
		return bestFound;
	}
} //end localOptimum
Пример #13
0
/**
 * Check if a knapsack contains a valid selection
 * @param k the knapsack instance to check
 */
bool checkValid(knapsack &k)
{
	return (k.getCost() < k.getCostLimit());
}
Пример #14
0
void branchAndBound(knapsack &k, int maxTime)
// Implement a Branch and Bound search for an optimal solution.
// Searches for the best decision for objects n and greater, as long
// as more than maxTime seconds have not elapsed.  Tries
// to keep or not keep object n, and then iterates to n+1.  Stores
// the best solution found so far in bestSolution.  
{
	clock_t endTime, startTime = clock();

	deque<knapsack> problem;
	deque<knapsack>::iterator itr;
	int number,bestValue=0;
	knapsack bestSolution;
	double time=0;

	cout<<"Branching and Bounding"<<endl;

	// Initially, decisions have not been made about any objects,
	// so set num = 0.
	k.setNum(0);

	// Add the empty knapsack subproblem to the list
	problem.push_front(k);

	// Branch and Bound search goes here
	while (!(problem.empty()) && (time<=maxTime)) //for each object in the deque
	{
		k = problem.back(); // current instance is now the last object in the deque
		while((k.getNum()!=k.getNumObjects()) && (k.bound()> bestValue) && (time<=maxTime))
			/*if we haven't considered all the objects left and the bound of the current instance 
			is not worse than our best-so-far solution and we are not out of time*/
		{
			//delete the last object from the deque because we are currently solving it
			problem.pop_back(); 
			number=k.getNum();
			k.setNum(number+1); //we are now considering the next object
			if(k.getCostBound()-k.getCurrentCost()>k.getCost(number))
			{
				problem.push_back(k); //push the 'don't select' instacne before the take instance
				k.select(number);
			}
			problem.push_back(k); //push the remaining instance

			endTime=clock();//update current time
			time=((double)(endTime-startTime))/CLOCKS_PER_SEC;
		}
		if (k.getCurrentValue() > bestValue){// replace best values if current ones are better
			bestValue = k.getCurrentValue();
			bestSolution = k;
		}
		problem.pop_back(); //delete the last object from the deque since it is fathomed
	}


	cout << "Best value found: " << bestValue << endl;
	cout << bestSolution;
	k.outFile(bestSolution);
}