public void addAll(BarSets barSets2) { // Check and add to existing bar set foreach (BarSet bs2 in barSets2.barSets) { if (bs2.num == 0) { continue; } bool isExist = false; foreach (BarSet bs1 in barSets) { if (bs1.len == bs2.len) { bs1.num += bs2.num; isExist = true; break; } } // Add new bar set if the len not exist in this BarSets if (!isExist) { barSets.Add(new BarSet(bs2.len, bs2.num)); } } }
/** * Main solver with threshold * * @param orderSets list of object of order length & order's length * @param stockLen raw bar length to cut * @return Map of cutting pattern and num of them */ public Dictionary <List <BarSet>, int> solve(List <BarSet> orderSets, double stockLen) { List <BarSet> newOrders = removeOrderLongerThanStock(orderSets, stockLen); BarSets orders = new BarSets(newOrders); orders.sortDesc(); Dictionary <BarSets, int> pttrnMap = new Dictionary <BarSets, int>(); while (orders.count() > 0) { BarSets pttrn = optimizeToOneStock(stockLen, orders); if (pttrn == null) { // Can't solve with condition, return empty result break; } addPatternToDictionary(pttrnMap, pttrn); orders.substractAll(pttrn); } Dictionary <List <BarSet>, int> rstMap = new Dictionary <List <BarSet>, int>(); foreach (KeyValuePair <BarSets, int> entry in pttrnMap) { rstMap.Add(entry.Key.getBarSets(), entry.Value); } return(rstMap); }
public void TestOptimizeToOneStock_WithCantCutCondition_ExpectNull(double stock, double minLeftover, double maxLeftover, double[] orderLens, int[] orderNums) { BarSets orders = initPattern(orderLens, orderNums); MinMaxSolver sut = new MinMaxSolver(minLeftover, maxLeftover); BarSets ret = sut.optimizeToOneStock(stock, orders); Assert.Null(ret); }
public void TestAddPatternToDictionary() { var dic = new Dictionary <BarSets, int>(); BarSets bs1 = initPattern(new double[] { 35d }, new int[] { 1 }); BarSets addedBs = initPattern(new double[] { 30d }, new int[] { 1 }); dic.Add(bs1, 2); MinMaxSolver.addPatternToDictionary(dic, addedBs); Assert.False(bs1.compareEqualWith(addedBs)); Assert.Equal(2, dic.Count); }
public void TestOptimizeToOneStock(double stock, double minLeftover, double maxLeftover, double[] orderLens, int[] orderNums, double[] expectedNewPttrnPopLens) { BarSets orders = initPattern(orderLens, orderNums); MinMaxSolver sut = new MinMaxSolver(minLeftover, maxLeftover); BarSets pattern = sut.optimizeToOneStock(stock, orders); pattern.sortAsc(); Assert.Equal(expectedNewPttrnPopLens.Length, pattern.count()); foreach (double expectedPopLen in expectedNewPttrnPopLens) { Assert.Equal(expectedPopLen, pattern.popLen()); } }
public void TestCalKnapsack(double stock, double minLeftover, double maxLeftover, double[] orderLens, int[] orderNums, double[] expectedNewPttrnPopLens) { BarSets orders = initPattern(orderLens, orderNums); BarSets ret = MinMaxSolver.calKnapsack(stock, orders); ret.sortAsc(); // Assert.Equal("", ret.ToString()); Assert.Equal(expectedNewPttrnPopLens.Length, ret.count()); foreach (double expectedPopLen in expectedNewPttrnPopLens) { Assert.Equal(expectedPopLen, ret.popLen()); } }
/** * Select the most optimized cut but doesn't violate the min max condition * It won't return empty bar sets */ private static bool isValidOptimizedPattern(double stockLen, BarSets pttn, double minLeftOver, double maxLeftOver) { if (pttn == null || pttn.isEmpty()) { return(false); } double leftOver = stockLen - pttn.countTotalLen(); if (leftOver < maxLeftOver && leftOver > minLeftOver) { return(false); } return(true); }
/** * If bar sets with same pattern is exist, add up the count only * if not exist, add new pattern with count = 1 to dictionary */ public static void addPatternToDictionary(Dictionary <BarSets, int> dic, BarSets barSets) { List <BarSets> bsKeys = new List <BarSets>(dic.Keys); foreach (BarSets bsKey in bsKeys) { if (bsKey.compareEqualWith(barSets)) { dic[bsKey] += 1; return; } } // If not exist add dic.Add(barSets, 1); }
public BarSets optimizeToOneStock(double stockLen, BarSets orders) { BarSets optimizedBarSets = calKnapsack(stockLen, orders); if (isValidOptimizedPattern(stockLen, optimizedBarSets, minLeftOver, maxLeftOver)) { return(optimizedBarSets); } // If we failed, try to get pattern with usable leftover optimizedBarSets = calKnapsack(stockLen - maxLeftOver, orders); if (isValidOptimizedPattern(stockLen, optimizedBarSets, minLeftOver, maxLeftOver)) { return(optimizedBarSets); } return(null); }
public static BarSets calKnapsack(double stockLen, BarSets orders) { List <BarSet> bsOrders = orders.getBarSets(); double[] orderNumVec = new double[bsOrders.Count + 1]; double[] orderLenVec = new double[bsOrders.Count + 1]; orderNumVec[0] = bsOrders.Count; orderLenVec[0] = bsOrders.Count; for (int i = 0; i < bsOrders.Count; i++) { orderNumVec[i + 1] = bsOrders[i].num; orderLenVec[i + 1] = bsOrders[i].len; } double[][] rstMap = calKnapsackWithLpSolve(stockLen, orderNumVec, orderLenVec); double[] patternVec = rstMap[1]; return(filterEmptyBarInPattern(bsOrders, patternVec)); }
public bool compareEqualWith(BarSets comparedBarSets) { List <BarSet> bs1 = new BarSets(barSets).sortAsc().getBarSets(); List <BarSet> bs2 = new BarSets(comparedBarSets.getBarSets()).sortAsc().getBarSets(); if (bs1.Count != bs2.Count) { return(false); } for (int i = 0; i < bs1.Count; i++) { if (bs1[i].len != bs2[i].len || bs1[i].num != bs2[i].num) { return(false); } } return(true); }
/** * @return true if can subtract */ public bool substractAll(BarSets substractBarSets) { List <BarSet> rstBarSets = new BarSets(this.barSets).getBarSets(); foreach (BarSet bs in substractBarSets.barSets) { foreach (BarSet originBs in rstBarSets) { if (originBs.len == bs.len) { if (originBs.num < bs.num) { // Invalid case return(false); } originBs.num = originBs.num - bs.num; } } } this.barSets = removeInvalidBarSet(rstBarSets); return(true); }