KnapsackResult GreedyResult(KnapsackInstance instance, IOrderedEnumerable <KnapsackItem> sortedItems) { var addedItemsVector = new bool[instance.ItemCount]; var currentWeight = 0; var currentPrice = 0; foreach (var item in sortedItems) { if (currentWeight + item.Weight > instance.KnapsackSize) { break; } currentPrice += item.Price; currentWeight += item.Weight; addedItemsVector[item.Id] = true; } return(new KnapsackResult { KnapsackInstance = instance, Configuration = new KnapsackConfiguration { ItemVector = addedItemsVector.ToList(), Price = currentPrice, Weight = currentWeight } }); }
public override ConstructiveResult Solve(KnapsackInstance instance) { if (instance.ItemCount == 0) { return new ConstructiveResult { KnapsackInstance = instance, Configuration = new KnapsackConfiguration { ItemVector = new List <bool>(), Price = 0, Weight = 0 } } } ; FillTable(instance); int bestPrice; var bestCell = FindBestCell(instance, out bestPrice); var itemVector = GetItemVector(bestCell); var knapsackConfiguration = new KnapsackConfiguration { ItemVector = itemVector, Price = bestPrice }; return(new ConstructiveResult { KnapsackInstance = instance, Configuration = knapsackConfiguration }); }
/// <summary> /// Because some items might be removed from the knapsack before reaching the DP algorithm /// (due to being single-handedly too big for the knapsack), the item vector needs to be expanded /// to include these removed items (they will always be a 0 in the vector) /// </summary> /// <param name="result"></param> /// <param name="originalInstance"></param> /// <returns></returns> List <bool> ConvertItemVector(IList <bool> itemVector, KnapsackInstance originalInstance) { //No items were removed if (itemVector.Count == originalInstance.ItemCount) { return(itemVector.ToList()); } var updatedSolutionVector = new List <bool>(); var solutionVectorIndex = 0; //Go through every item in the original instance foreach (var item in originalInstance.Items) { //This item was removed, add it into the item vector if (item.Weight > originalInstance.KnapsackSize) { updatedSolutionVector.Add(false); } //This item was not removed, just copy the result else { updatedSolutionVector.Add(itemVector[solutionVectorIndex]); solutionVectorIndex++; } } return(updatedSolutionVector); }
private KnapsackConfiguration GetOptimalConfiguration(KnapsackInstance instance) { var branchAndBoundSolver = new BranchBoundSolver(); var optimalSolution = branchAndBoundSolver.Solve(instance); return(optimalSolution.Configuration); }
public override ConstructiveResult Solve(KnapsackInstance instance) { //Make a shallow copy of instances list in order to not affect next possible execution var sorted = new List <KnapsackItem>(instance.Items); sorted.OrderByDescending(i => i.Price / i.Weight); var addedItemsVector = new bool[instance.ItemCount]; var currentWeight = 0; var currentPrice = 0; foreach (var item in sorted) { if (currentWeight + item.Weight > instance.KnapsackSize) { break; } currentPrice += item.Price; currentWeight += item.Weight; addedItemsVector[item.Id] = true; } return(new ConstructiveResult { KnapsackInstance = instance, Configuration = new KnapsackConfiguration { ItemVector = addedItemsVector.ToList(), Price = currentPrice, Weight = currentWeight } }); }
public KnapsackResult Solve(KnapsackInstance instance) { var sorted = instance.Items.OrderByDescending(i => i.Price / i.Weight); var greedyResult = GreedyResult(instance, sorted); var biggestLegalItem = sorted.FirstOrDefault(i => i.Weight <= instance.KnapsackSize); var addedItemsVector = new bool[instance.ItemCount]; if (biggestLegalItem == null || biggestLegalItem.Price <= greedyResult.Configuration.Price) { return(greedyResult); } addedItemsVector[biggestLegalItem.Id] = true; return(new KnapsackResult { KnapsackInstance = instance, Configuration = new KnapsackConfiguration { ItemVector = addedItemsVector.ToList(), Price = biggestLegalItem.Price, Weight = biggestLegalItem.Weight } }); }
private DPCell FindBestCell(KnapsackInstance instance, out int bestPrice) { bestPrice = toVisit.Dequeue(); foreach (var priceIndex in toVisit) { if (priceIndex > bestPrice) { bestPrice = priceIndex; } } return(memoryTable[bestPrice, instance.ItemCount - 1]); }
private ConstructiveResult EmptyResult(KnapsackInstance instance) { return(new ConstructiveResult { KnapsackInstance = instance, Configuration = new KnapsackConfiguration { ItemVector = instance.Items.Select(i => false).ToList(), Price = 0, Weight = 0 }, Strategy = $"fptas (epsilon:{instance.ApproximationAccuracy})" }); }
private DPCell FindBestCell(KnapsackInstance instance) { DPCell bestCell = memoryTable[toVisit.Dequeue(), instance.ItemCount - 1]; foreach (var weightIndex in toVisit) { var currentCell = memoryTable[weightIndex, instance.ItemCount - 1]; if (currentCell.Value > bestCell.Value) { bestCell = currentCell; } } return(bestCell); }
public override ConstructiveResult Solve(KnapsackInstance instance) { //Select only the items that can fit into the backcpack and make a copy of them var modifiedItems = instance.Items .Where(i => i.Weight <= instance.KnapsackSize) .Select(i => new KnapsackItem { Price = i.Price, Weight = i.Weight }) .ToList(); if (modifiedItems.Count() == 0) { return(EmptyResult(instance)); } //Calculate the divider based on the desired accuracy and input instance double divider = instance.ApproximationAccuracy * (double)modifiedItems.Max(i => i.Price) / modifiedItems.Count(); //Convert the price of each item foreach (var item in modifiedItems) { item.Price = (int)Math.Floor(item.Price / divider); } //Create a new instance for the DP solver var newKnapsackInstance = new KnapsackInstance { ApproximationAccuracy = instance.ApproximationAccuracy, Id = instance.Id, Items = modifiedItems, KnapsackSize = instance.KnapsackSize }; var dpPriceStrategy = new ConstructiveDPPrice(); var solution = dpPriceStrategy.Solve(newKnapsackInstance); //Include the removed items in the result item vector solution.Configuration.ItemVector = ConvertItemVector(solution.Configuration.ItemVector, instance); solution.KnapsackInstance = instance; //Calculate the total price using the solution item vector and the original item prices var solutionPrice = instance.Items.Aggregate(0, (acc, item) => acc + item.Price * Convert.ToInt32(solution.Configuration.ItemVector[item.Id])); solution.Configuration.Price = solutionPrice; solution.Strategy = $"fptas (epsilon:{instance.ApproximationAccuracy})"; return(solution); }
public override ConstructiveResult Solve(KnapsackInstance instance) { ConstructiveStrategy strategy; if (instance.KnapsackSize < instance.GetPriceOfAllItems()) { strategy = new ConstructiveDPCapacity(); } else { strategy = new ConstructiveDPPrice(); } return(strategy.Solve(instance)); }
protected void FillTable(KnapsackInstance instance) { InitializeTable(instance); for (int itemIndex = 0; itemIndex < instance.ItemCount - 1; itemIndex++) { var toVisitNext = new Queue <int>(); //Only visit the cells that have been added in the previous go foreach (var weight in toVisit) { //do not add item TryAddCell(weight, itemIndex, instance.KnapsackSize, toVisitNext); //add item TryAddCell(weight, itemIndex, instance.KnapsackSize, toVisitNext, instance.Items[itemIndex + 1]); } toVisit = toVisitNext; } }
public KnapsackResult Solve(KnapsackInstance instance) { BestConfiguration = new KnapsackConfiguration { Price = 0, Weight = 0, ItemVector = new bool[instance.ItemCount].ToList() }; FindBestConfiguration(0, new KnapsackConfiguration { Price = 0, Weight = 0, ItemVector = new List <bool>() }, instance.GetPriceOfAllItems(), instance); var result = new KnapsackResult { KnapsackInstance = instance, Configuration = BestConfiguration }; return(result); }
public override ConstructiveResult Solve(KnapsackInstance instance) { FillTable(instance); var bestCell = FindBestCell(instance); var itemVector = GetItemVector(bestCell); var knapsackConfiguration = new KnapsackConfiguration { ItemVector = itemVector, Price = bestCell.Value }; return(new ConstructiveResult { KnapsackInstance = instance, Configuration = knapsackConfiguration }); }
public override ConstructiveResult Solve(KnapsackInstance instance) { BestConfiguration = new KnapsackConfiguration { Price = int.MinValue, Weight = 0, ItemVector = CreateEmptySolution(instance.ItemCount) }; FindBestConfiguration(0, new KnapsackConfiguration { Price = 0, Weight = 0, ItemVector = new List <bool>() }, instance.GetPriceOfAllItems(), instance); var result = new ConstructiveResult { KnapsackInstance = instance, NumberOfSteps = numberOfSteps, Configuration = BestConfiguration }; return(result); }
protected override void InitializeTable(KnapsackInstance instance) { memoryTable = new DPCell[instance.KnapsackSize + 1, instance.ItemCount]; toVisit = new Queue <int>(); toVisit.Enqueue(0); memoryTable[0, 0] = new DPCell { AddedItem = false, Value = 0 }; var firstItem = instance.Items.First(); if (firstItem.Weight <= instance.KnapsackSize) { toVisit.Enqueue(firstItem.Weight); memoryTable[firstItem.Weight, 0] = new DPCell { AddedItem = true, Value = firstItem.Price }; } }
public override ConstructiveResult Solve(KnapsackInstance instance) { BestConfiguration = new KnapsackConfiguration { Price = int.MinValue, Weight = 0, ItemVector = new List <bool>() }; numberOfSteps = 0; FindBestConfiguration(0, new KnapsackConfiguration { Price = 0, Weight = 0, ItemVector = new List <bool>() }, instance); var result = new ConstructiveResult { KnapsackInstance = instance, NumberOfSteps = numberOfSteps, Configuration = BestConfiguration }; return(result); }
public override ConstructiveResult Solve(KnapsackInstance instance) { var greedyStrategy = new ConstructiveGreedy(); var greedySolution = greedyStrategy.Solve(instance); var sorted = new List <KnapsackItem>(instance.Items); sorted.OrderByDescending(i => i.Price); var addedItemsVector = new bool[instance.ItemCount]; var currentPrice = 0; var currentWeight = 0; foreach (var item in sorted) { if (item.Weight <= instance.KnapsackSize) { currentPrice = item.Price; currentWeight = item.Weight; addedItemsVector[item.Id] = true; } } if (currentPrice <= greedySolution.Configuration.Price) { return(greedySolution); } return(new ConstructiveResult { KnapsackInstance = instance, Configuration = new KnapsackConfiguration { ItemVector = addedItemsVector.ToList(), Price = currentPrice, Weight = currentWeight } }); }
public SimulatedAnnealingSolver(KnapsackInstance instance, AnnealingOptions options) { Instance = instance; Options = options; NumberOfSteps = 0; }
private void FindBestConfiguration(int itemIndex, KnapsackConfiguration currentConfiguration, KnapsackInstance instance) { numberOfSteps++; if (itemIndex > instance.ItemCount - 1) { if (currentConfiguration.Weight <= instance.KnapsackSize && currentConfiguration.Price > BestConfiguration.Price) { BestConfiguration = currentConfiguration; } return; } var currentItem = instance.Items[itemIndex]; var leftConfiguration = new KnapsackConfiguration { Price = currentConfiguration.Price, Weight = currentConfiguration.Weight, ItemVector = new List <bool>(currentConfiguration.ItemVector) }; leftConfiguration.ItemVector.Add(false); var rightConfiguration = new KnapsackConfiguration { Price = currentConfiguration.Price + currentItem.Price, Weight = currentConfiguration.Weight + currentItem.Weight, ItemVector = new List <bool>(currentConfiguration.ItemVector) }; rightConfiguration.ItemVector.Add(true); FindBestConfiguration(itemIndex + 1, leftConfiguration, instance); FindBestConfiguration(itemIndex + 1, rightConfiguration, instance); }
protected abstract void InitializeTable(KnapsackInstance instance);
private void FindBestConfiguration(int itemIndex, KnapsackConfiguration currentConfiguration, int remainingItemsPrice, KnapsackInstance instance) { numberOfSteps++; //Check for a leaf node if (itemIndex > instance.ItemCount - 1) { if (currentConfiguration.Weight <= instance.KnapsackSize && currentConfiguration.Price > BestConfiguration.Price) { BestConfiguration = currentConfiguration; } return; } //Check for price bound if (currentConfiguration.Price + remainingItemsPrice <= BestConfiguration.Price) { return; } //Check for weight overload if (currentConfiguration.Weight > instance.KnapsackSize) { return; } var currentItem = instance.Items[itemIndex]; var leftConfiguration = new KnapsackConfiguration { Price = currentConfiguration.Price, Weight = currentConfiguration.Weight, ItemVector = new List <bool>(currentConfiguration.ItemVector) }; leftConfiguration.ItemVector.Add(false); var rightConfiguration = new KnapsackConfiguration { Price = currentConfiguration.Price + currentItem.Price, Weight = currentConfiguration.Weight + currentItem.Weight, ItemVector = new List <bool>(currentConfiguration.ItemVector) }; rightConfiguration.ItemVector.Add(true); FindBestConfiguration(itemIndex + 1, leftConfiguration, remainingItemsPrice - currentItem.Price, instance); FindBestConfiguration(itemIndex + 1, rightConfiguration, remainingItemsPrice - currentItem.Price, instance); }