Ejemplo n.º 1
0
        /**
         * This func generate all possible pattern to be fit in one stock len (or remain stock len)
         * from the @param{curOrderIndex} to end of orderSets
         */
        public static List <List <BarSet> > calPossibleCutsFor1Stock(int curOrderIndex, List <BarSet> orderSets, double stockLen)
        {
            List <List <BarSet> > possiblePatterns = new List <List <BarSet> >();

            bool canCut = checkCanCut(orderSets, stockLen);

            if (!canCut)
            {
                // Create array to let father func put bar in
                possiblePatterns.Add(new List <BarSet>());
                return(possiblePatterns);
            }

            if (curOrderIndex == orderSets.Count)
            {
                return(possiblePatterns);
            }

            BarSet curOrderSet = orderSets[curOrderIndex];
            int    maxBarNum   = minInt((int)(stockLen / curOrderSet.len), curOrderSet.num);

            for (int nBar = 0; nBar <= maxBarNum; nBar++)
            {
                // Clone current order except the one at current index
                List <BarSet> remainOrderSets = new List <BarSet>();
                remainOrderSets.AddRange(orderSets);
                remainOrderSets[curOrderIndex] = new BarSet(curOrderSet.len, curOrderSet.num - nBar);

                List <List <BarSet> > subPatterns = calPossibleCutsFor1Stock(
                    curOrderIndex + 1, remainOrderSets, stockLen - curOrderSet.len * nBar);

                int barNum = nBar;
                foreach (List <BarSet> pttrn in subPatterns)
                {
                    pttrn.Insert(0, new BarSet(curOrderSet.len, barNum));
                }
                possiblePatterns.AddRange(subPatterns);
            }

            return(possiblePatterns);
        }
        /**
         * Solve most of pattern by linear programming
         * @returns 1st value is optimized pattern, 2nd value is the remain orders that haven't been solved
         */
        public static Pair <Dictionary <List <BarSet>, int>, List <BarSet> > solveByLinearProgramming(List <BarSet> orderSets, double stockLen)
        {
            int nOrder = orderSets.Count;

            // Convert to Lp solve-friendly format: [arrayLen, x1, x2, 3...]
            double[] odLenVec = new double[nOrder + 1]; // order length vector
            double[] odNumVec = new double[nOrder + 1]; // order number vector
            odLenVec[0] = nOrder;
            odNumVec[0] = nOrder;
            for (int i = 0; i < nOrder; i++)
            {
                BarSet barSet = orderSets[i];
                odLenVec[i + 1] = barSet.len;
                odNumVec[i + 1] = barSet.num;
            }

            double[][] patternMat     = genPatternMatrix(odLenVec, odNumVec, stockLen);
            double[]   minPatternNums = new double[nOrder];

            // Lpsolve.Init(".");
            int iter;

            for (iter = 0; iter < MAX_ITER; iter++)
            {
                ;
                // Solve Linear Programming problem
                double[][] lpRst   = calLP(patternMat, odNumVec);
                int        solFlag = (int)lpRst[0][0];
                if (solFlag != (int)Lpsolve.lpsolve_return.OPTIMAL)
                {
                    Console.WriteLine("Can't solve anymore");
                    break;
                }
                minPatternNums = lpRst[1];
                double[] dualCostVector = lpRst[2];

                // Solve Knapsack problem
                double[][] ksRst       = calKnapsack(dualCostVector, odLenVec, stockLen);
                double     reducedCost = ksRst[0][0];
                double[]   newPattern  = ksRst[1];

                // TODO: use native optimized variable instead
                if (reducedCost <= 1.000000000001)
                { // epsilon threshold due to double value error
                    Console.WriteLine("Optimized");
                    break;
                }

                // Cal leaving column
                int[] lcRst           = calLeavingColumn(patternMat, newPattern, minPatternNums);
                int   lcSolFlag       = lcRst[0];
                int   leavingColIndex = lcRst[1];
                // Console.WriteLine("Leaving column index: {0}", leavingColIndex);

                if (lcSolFlag != (int)Lpsolve.lpsolve_return.OPTIMAL)
                {
                    Console.WriteLine("Can't solve anymore");
                    break;
                }

                // Save new pattern
                for (int r = 0; r < patternMat.Length; r++)
                {
                    patternMat[r][leavingColIndex] = newPattern[r];
                }
            }

            if (iter == MAX_ITER)
            {
                Console.WriteLine("Maximum of iter reached! Solution is not quite optimized");
            }

            // ------------ Round up to keep integer part of result ----------------
            double[] remainOdNumVec = new double[odNumVec.Length];
            odNumVec.CopyTo(remainOdNumVec, 0);
            for (int r = 0; r < patternMat.Length; r++)
            {
                double[] row = patternMat[r];
                for (int c = 1; c < row.Length; c++)
                {
                    remainOdNumVec[r + 1] -= row[c] * Math.Floor(minPatternNums[c]);
                }
            }
            // Console.WriteLine("Leftovers: {0}", string.Join(", ", remainOdNumVec));

            // Optimized for the rest of pattern by BruteForce
            List <BarSet> remainOrderSets = new List <BarSet>();

            for (int r = 1; r < remainOdNumVec.Length; r++)
            {
                if (remainOdNumVec[r] > 0)
                {
                    remainOrderSets.Add(new BarSet(odLenVec[r], (int)remainOdNumVec[r]));
                }
            }

            // Prepare result
            Dictionary <List <BarSet>, int> rstMap = new Dictionary <List <BarSet>, int>();

            for (int c = 1; c < nOrder + 1; c++)
            {     // column
                if ((int)minPatternNums[c] == 0)
                { // if number of this pattern is zero, skip
                    continue;
                }

                List <BarSet> pattern = new List <BarSet>();
                for (int r = 0; r < nOrder; r++)
                { // row
                    if (patternMat[r][c] > 0d)
                    {
                        pattern.Add(new BarSet(odLenVec[r + 1], (int)patternMat[r][c]));
                    }
                }
                rstMap.Add(pattern, (int)minPatternNums[c]);
            }

            return(new Pair <Dictionary <List <BarSet>, int>, List <BarSet> >(rstMap, remainOrderSets));
        }