private int TryCreatingItemsByMerge(MyComponentGroupDefinition group, int itemValue, int itemCount) { // Removal buffer is here so that the method does not do anything until it's clear that the operation can be successful List<int> removalBuffer = m_listAllocator.Allocate(); removalBuffer.Clear(); for (int i = 0; i <= group.GetComponentNumber(); ++i) { removalBuffer.Add(0); } int createdCount = 0; // Create the items one-by-one for (int i = 0; i < itemCount; ++i) { // What remains to be found to create this item int remainder = itemValue; // Fill this item with smaller items as long as possible for (int k = itemValue - 1; k >= 1; k--) { int amount = 0; if (m_presentItems.TryGetValue(k, out amount)) { int removeCount = Math.Min(remainder / k, amount); if (removeCount > 0) { remainder = remainder - k * removeCount; amount -= removeCount; removalBuffer[k] += removeCount; } } } // The remainder was not reduced by the remaining items, which means that we don't have any items left if (remainder == itemValue) { Debug.Assert(m_presentItems.Count == 0 || itemValue == 1, "There are still items present in the cutting solver, but they were not used in the solution!"); break; } // There are no more smaller items to fill the remainder. Try to split one of the larger ones if (remainder != 0) { for (int j = remainder + 1; j <= group.GetComponentNumber(); ++j) { int present = 0; m_presentItems.TryGetValue(j, out present); // If there is some present item that is not planned to be removed, use it if (present > removalBuffer[j]) { MyDefinitionId removedComponentId = group.GetComponentDefinition(j).Id; MyDefinitionId addedComponentId = group.GetComponentDefinition(j - remainder).Id; AddChangeToSolution(removedComponentId, addedComponentId, 1); int removed = TryRemovePresentItems(j, 1); AddPresentItems(j - remainder, 1); Debug.Assert(removed == 1); remainder = 0; break; } } } if (remainder == 0) { createdCount++; // Add the buffered removals of the smaller items here for (int k = 1; k <= group.GetComponentNumber(); ++k) { if (removalBuffer[k] > 0) { MyDefinitionId removedComponentId = group.GetComponentDefinition(k).Id; int removed = TryRemovePresentItems(k, removalBuffer[k]); Debug.Assert(removed == removalBuffer[k]); AddRemovalToSolution(removedComponentId, removalBuffer[k]); removalBuffer[k] = 0; // We need to clear the buffer for the next item } } } // The item could not be created and neither would be the others else if (remainder > 0) break; } m_listAllocator.Deallocate(removalBuffer); return createdCount; }
private void UpdatePresentItems(MyComponentGroupDefinition group, Dictionary<MyDefinitionId, MyFixedPoint> componentCounts) { m_presentItems.Clear(); for (int i = 1; i <= group.GetComponentNumber(); i++) { var compDef = group.GetComponentDefinition(i); MyFixedPoint amount = 0; componentCounts.TryGetValue(compDef.Id, out amount); m_presentItems[i] = (int)amount; } }
private int TryCreatingItemsBySplit(MyComponentGroupDefinition group, int itemValue, int itemCount) { int createdCount = 0; // Avoid making too much "mess" by trying to find the best-fitting items first for (int k = itemValue + 1; k <= group.GetComponentNumber(); k++) { int fitNumber = k / itemValue; // How many items fit into k-item int wholeCount = itemCount / fitNumber; // How many k-items will be fully split int partialFitNumber = itemCount % fitNumber; // How many items will be created from the last k-item int partialCount = partialFitNumber == 0 ? 0 : 1; // How many k-items will be partially split (either 0 or 1 that is) int removedCount = TryRemovePresentItems(k, wholeCount + partialCount); if (removedCount > 0) { int removedWholeCount = Math.Min(removedCount, wholeCount); if (removedWholeCount != 0) { int created = SplitHelper(group, k, itemValue, removedWholeCount, fitNumber); createdCount += created; itemCount -= created; } if (removedCount - wholeCount > 0) { Debug.Assert(removedCount == wholeCount + partialCount && partialCount == 1, "Calculation problem in cutting solver"); int created = SplitHelper(group, k, itemValue, 1, partialFitNumber); createdCount += created; itemCount -= created; } } } return createdCount; }