/// <summary> /// Conventional 2-approximation algorithm for 0-1KP /// Result, r holds to outcome that optimal solution, z* is less than or equal to 2r /// i.e. 2r provides upper bound for profit /// </summary> /// <returns></returns> public static int Conventional2Approx_KP(List <Item> items, Knapsack knapsack) { ItemGroup group = new ItemGroup(); List <Item> sortedItems = UtilFunctions.SortByUnitProfitDescending(items); // Fill until we reach critical item foreach (Item item in sortedItems) { if (group.TotalWeight() + item.Weight <= knapsack.Capacity) { group.AddItem(item); } else // we have reached critical item { var criticalItem = item; // 2-approximation solution is one with higher profit value of group or criticalItem if (criticalItem.Value > group.TotalValue()) { group = (ItemGroup) new ItemGroup().Add(criticalItem); } break; } } return(group.TotalValue()); }
private void WriteSolutionAndData(ItemGroup requiredValueGroup) { LogFile.WriteLine("Maximum value after choosing {0} of first {1} items at weight {2} is {3}", _knapsack.AllowedItems, _items.Count, _knapsack.Capacity, requiredValueGroup.TotalValue() ); LogFile.WriteLine("No of items: {0}", requiredValueGroup.ItemCount()); LogFile.WriteLine("Item names: {0}", requiredValueGroup.ItemNames()); LogFile.WriteLine("Total weight: {0}", requiredValueGroup.TotalWeight()); LogFile.WriteLine("Total value: {0}", requiredValueGroup.TotalValue()); Console.WriteLine("Maximum value after choosing {0} of first {1} items at weight {2} is {3}", _knapsack.AllowedItems, _items.Count, _knapsack.Capacity, requiredValueGroup.TotalValue() ); Console.WriteLine("No of items: {0}", requiredValueGroup.ItemCount()); Console.WriteLine("Item names: {0}", requiredValueGroup.ItemNames()); Console.WriteLine("Total weight: {0}", requiredValueGroup.TotalWeight()); Console.WriteLine("Total value: {0}", requiredValueGroup.TotalValue()); DumpArrayToLog(m => m.TotalValue()); DumpArrayToLog(m => m.ItemCount()); }
public void CalculateRecursive() { int currentCapacity = _knapsack.Capacity; ItemGroup requiredValueGroup = GetMaxValue(_items.Count, currentCapacity, _knapsack.AllowedItems); // Actual solution is not simply finding a value at capacity and allowed items // because we are only solving for kKP (not E-kKP) // Actually want to find value at AllowedItems, but potentially at lower capacity, with ItemCount = AllowedItems while (requiredValueGroup.ItemCount() < _knapsack.AllowedItems) { if (--currentCapacity == 0) { break; } requiredValueGroup = GetMaxValue(_items.Count, currentCapacity, _knapsack.AllowedItems); } if (currentCapacity == 0) { Console.WriteLine( "There is no valid solution with capacity constraint of {0} and count constraint of {1}.", _knapsack.Capacity, _knapsack.AllowedItems); return; } LogFile.WriteLine("Maximum value after choosing {0} of first {1} items at weight {2} is {3}", _knapsack.AllowedItems, _items.Count, _knapsack.Capacity, requiredValueGroup.TotalValue() ); LogFile.WriteLine("No of items: {0}", requiredValueGroup.ItemCount()); LogFile.WriteLine("Item names: {0}", requiredValueGroup.ItemNames()); LogFile.WriteLine("Total weight: {0}", requiredValueGroup.TotalWeight()); LogFile.WriteLine("Total value: {0}", requiredValueGroup.TotalValue()); Console.WriteLine("Maximum value after choosing {0} of first {1} items at weight {2} is {3}", _knapsack.AllowedItems, _items.Count, _knapsack.Capacity, requiredValueGroup.TotalValue() ); Console.WriteLine("No of items: {0}", requiredValueGroup.ItemCount()); Console.WriteLine("Item names: {0}", requiredValueGroup.ItemNames()); Console.WriteLine("Total weight: {0}", requiredValueGroup.TotalWeight()); Console.WriteLine("Total value: {0}", requiredValueGroup.TotalValue()); }
private void WriteSolutionAndData() { bool exactSolutionExists = Exact_K_SolutionExists(); if (exactSolutionExists) { ItemGroup maxProfitGroup = GetSolution(_knapsack.AllowedItems); Console.WriteLine("Solution exists for exactly {0} items", _knapsack.AllowedItems); Console.WriteLine(" No of items: {0}", maxProfitGroup.ItemCount()); Console.WriteLine(" Item names: {0}", maxProfitGroup.ItemNames()); Console.WriteLine(" Total weight: {0}", maxProfitGroup.TotalWeight()); Console.WriteLine(" Total value: {0}", maxProfitGroup.TotalValue()); } ItemGroup optimalGroup = GetOptimalSolution(); Console.WriteLine("Optimal value solution:"); Console.WriteLine(" No of items: {0}", optimalGroup.ItemCount()); Console.WriteLine(" Item names: {0}", optimalGroup.ItemNames()); Console.WriteLine(" Total weight: {0}", optimalGroup.TotalWeight()); Console.WriteLine(" Total value: {0}", optimalGroup.TotalValue()); //DumpArrayToLog(m => m.TotalValue()); //DumpArrayToLog(m => m.ItemCount()); }
/// <summary> /// Uses greedy algorithm to get approximation of highest value for profit /// </summary> /// <returns></returns> public static double LPRelaxedApprox_KP(List <Item> items, Knapsack knapsack) { ItemGroup group = new ItemGroup(); List <Item> sortedItems = UtilFunctions.SortByUnitProfitDescending(items); Item criticalItem = new Item("", 0, 0); double criticalItemFraction = 0; // Fill until we reach critical item foreach (Item item in sortedItems) { if (group.TotalWeight() + item.Weight <= knapsack.Capacity) { group.AddItem(item); } else // we have reached critical item { criticalItem = item; criticalItemFraction = (knapsack.Capacity - group.TotalWeight()) / (double)criticalItem.Weight; break; } } // Add fractional value of next item double maxProfitValue = group.TotalValue() + criticalItem.Value * criticalItemFraction; return(maxProfitValue); }
public ItemGroup GetMaxValue(int forFirstN, int atWeight, int itemsChosen) { // value at 0 items or 0 weight, or 0 items chosen is 0 if (forFirstN == 0 || atWeight <= 0 || itemsChosen == 0) { return(new ItemGroup()); } // calculate the previous value if (_maxValues[forFirstN - 1, atWeight, itemsChosen] is null) { _maxValues[forFirstN - 1, atWeight, itemsChosen] = GetMaxValue(forFirstN - 1, atWeight, itemsChosen); } // if current item weight is greater than weight being calculated, don't add the value if (_items[forFirstN - 1].Weight > atWeight) { _maxValues[forFirstN, atWeight, itemsChosen] = new ItemGroup(_maxValues[forFirstN - 1, atWeight, itemsChosen]); } else { ItemGroup withoutCurrentItem = _maxValues[forFirstN - 1, atWeight - _items[forFirstN - 1].Weight, itemsChosen - 1]; // if we haven't calculated max without current item, do it now if (withoutCurrentItem is null) { withoutCurrentItem = GetMaxValue(forFirstN - 1, atWeight - _items[forFirstN - 1].Weight, itemsChosen - 1); _maxValues[forFirstN - 1, atWeight - _items[forFirstN - 1].Weight, itemsChosen - 1] = withoutCurrentItem; } // add item to prev ItemGroup withCurrentItem = (ItemGroup) new ItemGroup(withoutCurrentItem).Add(_items[forFirstN - 1]); if (_maxValues[forFirstN - 1, atWeight, itemsChosen].TotalValue() >= withCurrentItem.TotalValue()) { _maxValues[forFirstN, atWeight, itemsChosen] = new ItemGroup(_maxValues[forFirstN - 1, atWeight, itemsChosen]); } else { _maxValues[forFirstN, atWeight, itemsChosen] = withCurrentItem; } } //LogFile.WriteLine("Maximum value after choosing {3} of first {0} items at weight {1} is {2}", // forFirstN, // atWeight, // _maxValues[forFirstN, atWeight, itemsChosen].TotalValue(), // itemsChosen); //LogFile.WriteLine("Items: {0}, Count: {1}, Total weight: {2}", // _maxValues[forFirstN, atWeight, itemsChosen].ItemNames(), // _maxValues[forFirstN, atWeight, itemsChosen].ItemCount(), // _maxValues[forFirstN, atWeight, itemsChosen].TotalWeight()); return(_maxValues[forFirstN, atWeight, itemsChosen]); }
private void WriteSolutionAndData() { ItemGroup requiredValueGroup = _maxProfitItemGroup[_items.Count, _knapsack.Capacity]; Console.WriteLine("Maximum value for first {0} items at weight {1} is {2}", _items.Count, _knapsack.Capacity, requiredValueGroup.TotalValue()); Console.WriteLine("No of items: {0}", requiredValueGroup.ItemCount()); Console.WriteLine("Item names: {0}", requiredValueGroup.ItemNames()); Console.WriteLine("Total weight: {0}", requiredValueGroup.TotalWeight()); Console.WriteLine("Total value: {0}", requiredValueGroup.TotalValue()); DumpArrayToLog(m => m.TotalValue()); DumpArrayToLog(m => m.ItemCount()); }
private ItemGroup GetSolution(int numberOfItems) { ItemGroup maxProfitGroup = new ItemGroup(); int itemsUpperBound = _maxProfitItemGroup.GetUpperBound(ItemsConsideredDimension); // find maximum value where all items in list considered and count = allowed items for (int weight = 0; weight <= _maxProfitItemGroup.GetUpperBound(WeightDimension); weight++) { if (_maxProfitItemGroup[itemsUpperBound, numberOfItems, weight].TotalValue() > maxProfitGroup.TotalValue()) { maxProfitGroup = _maxProfitItemGroup[itemsUpperBound, numberOfItems, weight]; } } return(maxProfitGroup); }
private ItemGroup GetOptimalSolution() { ItemGroup maxProfitGroup = new ItemGroup(); int itemsUpperBound = _maxProfitItemGroup.GetUpperBound(ItemsConsideredDimension); // find maximum value where all items in list considered for (int itemsChosen = _maxProfitItemGroup.GetUpperBound(ItemsChosenDimension); itemsChosen >= 0; itemsChosen--) { var solutionWithNItems = GetSolution(itemsChosen); if (solutionWithNItems.TotalValue() > maxProfitGroup.TotalValue()) { maxProfitGroup = solutionWithNItems; } } return(maxProfitGroup); }
public void CalculateRecursive() { if (Exact_K_SolutionExists()) { ItemGroup maxProfitGroup = GetSolution(_knapsack.AllowedItems); Console.WriteLine("Solution exists for exactly {0} items", _knapsack.AllowedItems); Console.WriteLine(" No of items: {0}", maxProfitGroup.ItemCount()); Console.WriteLine(" Item names: {0}", maxProfitGroup.ItemNames()); Console.WriteLine(" Total weight: {0}", maxProfitGroup.TotalWeight()); Console.WriteLine(" Total value: {0}", maxProfitGroup.TotalValue()); } ItemGroup optimalGroup = GetOptimalSolution(); Console.WriteLine("Optimal value solution:"); Console.WriteLine(" No of items: {0}", optimalGroup.ItemCount()); Console.WriteLine(" Item names: {0}", optimalGroup.ItemNames()); Console.WriteLine(" Total weight: {0}", optimalGroup.TotalWeight()); Console.WriteLine(" Total value: {0}", optimalGroup.TotalValue()); }