Esempio n. 1
0
    Square(const SizeOptions& opt) : Script(opt), n(opt.size()),
    x(*this, opt.size(), 0, maxSourroundingSquareSize()), y(*this, opt.size(), 0, maxSourroundingSquareSize()),
    s(*this, maxSourroundingSquareSize(), sumN()) {
        
        // Every square must fit the surrounding square.
        for(int i = 0; i < n - 1; i++) {
            rel(*this, x[i] + size(i) <= s);
            rel(*this, y[i] + size(i) <= s);
        }
        
        // Symmetry removal.
        rel(*this, x[0], IRT_GQ, 0);
        rel(*this, x[0], IRT_LE, floor(((s.max() - n) / 2)));
        rel(*this, y[0], IRT_LQ, x[0]);
        
        // Empty strip dominance.
        if(n == 2) {
            rel(*this, x[0], IRT_LE, 2);
            rel(*this, y[0], IRT_LE, 2);
        } else if (n == 3) {
            rel(*this, x[0], IRT_LE, 3);
            rel(*this, y[0], IRT_LE, 3);
        } else if (n == 4) {
            rel(*this, x[0], IRT_LE, 2);
            rel(*this, y[0], IRT_LE, 2);
        } else if(n >= 5 && n <= 8) {
            rel(*this, x[0], IRT_LE, 3);
            rel(*this, y[0], IRT_LE, 3);
        } else if (n >= 9 && n <= 11) {
            rel(*this, x[0], IRT_LE, 4);
            rel(*this, y[0], IRT_LE, 4);
        } else if(n >= 12 && n <= 17) {
            rel(*this, x[0], IRT_LE, 5);
            rel(*this, y[0], IRT_LE, 5);
        } else if (n >= 18 && n <= 21) {
            rel(*this, x[0], IRT_LE, 6);
            rel(*this, y[0], IRT_LE, 6);
        } else if (n >= 22 && n <= 29) {
            rel(*this, x[0], IRT_LE, 7);
            rel(*this, y[0], IRT_LE, 7);
        } else if (n >= 30 && n <= 34) {
            rel(*this, x[0], IRT_LE, 8);
            rel(*this, y[0], IRT_LE, 8);
        } else if (n >= 35 && n <= 44) {
            rel(*this, x[0], IRT_LE, 9);
            rel(*this, y[0], IRT_LE, 9);
        } else if (n == 45) {
            rel(*this, x[0], IRT_LE, 10);
            rel(*this, y[0], IRT_LE, 10);
        }

    	// The last element (1x1) is not considered.
        for(int i = 0; i < n - 1; i++) {
        	for(int j = i + 1; j < n; j++) {
        		BoolVarArgs b(*this, 4, 0, 1);

        		// Left constraint.
        		rel(*this, LinIntExpr(x[i] + size(i)).post(*this, ICL_VAL), IRT_LQ,
        				LinIntExpr(x[j]).post(*this, ICL_VAL), b[0]);

        		// Right constraint.
        		rel(*this, LinIntExpr(x[i]).post(*this, ICL_VAL), IRT_GQ,
        				LinIntExpr(x[j] + size(j)).post(*this, ICL_VAL), b[1]);

        		// Below constraint.
        		rel(*this, LinIntExpr(y[i] + size(i)).post(*this, ICL_VAL), IRT_LQ,
        				LinIntExpr(y[j]).post(*this, ICL_VAL), b[2]);

        		// Above constraint.
        		rel(*this, LinIntExpr(y[i]).post(*this, ICL_VAL), IRT_GQ,
        				LinIntExpr(y[j] + size(j)).post(*this, ICL_VAL), b[3]);

                // At least one of the constraints expressed above must hold.
        		linear(*this, b, IRT_GQ, 1);
        	}
        }

        // The commented snippet below is the code used to test the implemented propagator no-overlap.

        // IntArgs w(n);
        // IntArgs h(n);
        // IntVarArgs x1(x);
        // IntVarArgs y1(y);
        
        // for(int i = 0; i < n; i++) {
        //     w[i] = size(i);
        //     h[i] = size(i);
        // }
        
        // nooverlap(*this, x1, w, y1, h);

        // Branching first on s.
        branch(*this, s, INT_VAL_MIN());
        branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_MIN());
        branch(*this, y, INT_VAR_SIZE_MIN(), INT_VAL_MIN());
    }
Esempio n. 2
0
        SquarePacking(const SizeOptions& opt) 
                : x(*this, opt.size()), y(*this, opt.size()) {
            // Step 1b: Initialize variables s, x, y
            int min = 0;
            int max = 0;
            for (int i = 0; i < opt.size(); ++i) {
                min += i*i;
                max += i;
            }
            s = IntVar(*this, sqrt(min), max);

            for (int i = 0; i < opt.size(); ++i) {
                x[i] = IntVar(*this, 0, max);
                y[i] = IntVar(*this, 0, max);
            }

            for (int i = 0; i < N; ++i) {
                rel(*this, (x[i] + size(i)) <= s);
                rel(*this, (y[i] + size(i)) <= s);
            }

            // Step 2: No overlapping between squares, expressed with
            // reification.
            for (int i = 0; i < N-1; i++) {
               for (int j = i+1; j < N-1; j++) {
                   rel(*this, 
                        (x[i] + size(i) <= x[j]) || 
                        (x[j] + size(j) <= x[i]) ||
                        (y[i] + size(i) <= y[j]) || 
                        (y[j] + size(j) <= y[i]));  
                }
            }

            // Step 3: Sum of square sizes for every row and column less than
            // s, expressed with reification.
            IntArgs sizes(N-1);
            for (int i = 0; i < N-1; ++i) {
                sizes[i] = size(i);
            }

            for (int col = 0; col < s.max(); ++col) {
                BoolVarArgs bx(*this, N-1, 0, 1);
                for (int i = 0; i < N-1; ++i) {
                    dom(*this, y[i], col - size(i) + 1, col, bx[i]);
                }
                linear(*this, sizes, bx, IRT_LQ, s);
            }

            for (int col = 0; col < s.max(); ++col) {
                BoolVarArgs bx(*this, N-1, 0, 1);
                for (int i = 0; i < N-1; ++i) {
                    dom(*this, x[i], col - size(i) + 1, col, bx[i]);
                }
                linear(*this, sizes, bx, IRT_LQ, s);
             }

            // Step 4.1: Problem decomposition 
            rel(*this, (s*s) > ((N * (N+1) * (2 * N+1))/6));

            // Step 4.2: Symmetry removal
            rel(*this, x[0] <= ((s - N)/2));
            rel(*this, y[0] <= ((s - N)/2));

            // Step 4.3: Empty strip dominance
            for (int i = 0; i < N; ++i) {
                int siz = size(i);
                int gt = 0;
                if (siz == 2 || siz == 4)
                    gt = 2;
                else if (siz == 3 || (siz >= 5 && siz <= 8))
                    gt = 3;
                else if (siz <= 11)
                    gt = 4;
                else if (siz <= 17)
                    gt = 5;
                else if (siz <= 21)
                    gt = 6;
                else if (siz <= 29)
                    gt = 7;
                else if (siz <= 34)
                    gt = 8;
                else if (siz <= 44)
                    gt = 9;
                else if (siz <= 45)
                    gt = 10;

                if (gt != 0) {
                    rel(*this, x[i] != gt);
                    rel(*this, y[i] != gt);
                }
            }

            // Step 4.4: Ignoring size 1 squares, this is done by only looping
            // until N-1 instead of N

            // Step 5: Branching heuristics
            branch(*this, s, INT_VAL_MIN); // (5a) Branch on s first

            // Interval branch
            IntArgs nsizes(N);
            for (int i = 0; i < N; ++i) {
                nsizes[i] = size(i);
            }
            interval(*this, x, nsizes, 0.6);
            interval(*this, y, nsizes, 0.6);

            // (5c) INT_VAR_NONE means going through the array in order, that
            // is from the biggest to the smallest square
            // (5d) INT_VAL_MIN chooses the minimum value, that is placing it
            // from left to right and top to botom.
            // (5b) First assign x-coordinates.     
            branch(*this, x, INT_VAR_NONE, INT_VAL_MIN);
            // (5b) then y-coordinates. 
            branch(*this, y, INT_VAR_NONE, INT_VAL_MIN);
        }
Esempio n. 3
0
 // n, nr of boxes, variables are from 0 to n. Should deduct index of array here.
 Square(const SizeOptions& opt) : Script(opt), xCoords(*this, opt.size()), yCoords(*this, opt.size()) {
     
     // Size must be at least n + (n - 1). Otherwise we cant fit both the largest and second largest.
     int min = n + (n - 1);
     
     // Max size of square is when all squares are on a single line.
     int max = 0;
     
     for (int i = 0; i < n; i++) {
         max += i;
     }
     
     // Initialize size with min and max values.
     size = IntVar(*this, min, max);
     
     // Initialize coordinate variables, values from 0 to max size.
     for (int i = 0; i < n; i++) {
         xCoords[i] = IntVar(*this, 0, max);
         yCoords[i] = IntVar(*this, 0, max);
     }
     
     // Constraints so squares wont escape its containing square.
     for (int i = 0; i < n; i++) {
         rel(*this, xCoords[i] + sizeOfSquare(i) <= size);
         rel(*this, yCoords[i] + sizeOfSquare(i) <= size);
     }
     
     // Constraints for non overlapping
     for (int i = 0; i < (n - 1); i++) {
         for (int j = i + 1; j < (n - 1); j++) { //Avoid some redundant constraints by initiating j = i + 1. Also never compare the square to itself.
             rel(*this, xCoords[i] + sizeOfSquare(i) <= xCoords[j] ||
                        xCoords[j] + sizeOfSquare(j) <= xCoords[i] ||
                        yCoords[i] + sizeOfSquare(i) <= yCoords[j] ||
                        yCoords[j] + sizeOfSquare(j) <= yCoords[i]);
         }
     }
     
     // Constraints for column/row consistency
     IntArgs squareSizes(n - 1);
     
     for (int i = 0; i < (n - 1); i++) {
         squareSizes[i] = sizeOfSquare(i);
     }
     
     // Loop through all columns
     for (int col = 0; col < size.max(); col++) {
         BoolVarArgs isCoveringCol(*this, (n - 1), 0, 1);
         // Loop through all squares
         for (int i = 0; i < (n - 1); i++) {
             // Coord of square inbetween column index - size + 1 and column index.
             dom(*this, xCoords[i], col - sizeOfSquare(i) + 1, col, isCoveringCol[i]);
         }
         //Get the size of squares covering column and add them. Must be less or equal to size of containing square.
         linear(*this, squareSizes, isCoveringCol, IRT_LQ, size);
     }
     
     // Loop through all rows
     for (int row = 0; row < size.max(); row++) {
         BoolVarArgs isCoveringRow(*this, (n - 1), 0, 1);
         // Loop through all squares
         for (int i = 0; i < (n - 1); i++) {
             dom(*this, yCoords[i], row - sizeOfSquare(i) + 1, row, isCoveringRow[i]);
         }
         linear(*this, squareSizes, isCoveringRow, IRT_LQ, size);
     }
     
     // Additional constraints
     
     // Problem decomposition - Size of container must be at least as large as the sum of all squares.
     rel(*this, (size * size) >= (n * (n + 1) * (2 * n + 1)) / 6);
     
     // Symmetry removal - Restrict coordinate of largest square to the first corner.
     rel(*this, xCoords[0] <= ((size - n) / 2));
     rel(*this, yCoords[0] <= ((size - n) / 2));
     rel(*this, yCoords[0] <= xCoords[0]);
     
     // Empty strip dominance, only disallowing placements away from top and left border.
     for (int i = 0; i < n; i++) {
         int disallowedPlacement = getDisallowedPlacement(sizeOfSquare(i));
         
         if (disallowedPlacement > 0) {
             rel(*this, xCoords[i], IRT_NQ, disallowedPlacement);
             rel(*this, yCoords[i], IRT_NQ, disallowedPlacement);
         }
     }
     
     // TODO: Forbidden gaps between squares
     
     // Ignoring size 1 squares
     // Not adding constaints for non overlapping or row/column consistency with the size 1 square. Using (n - 1) instead of n.
     
     // Branching, branch on size first.
     branch(*this, size, INT_VAL_MIN());
     //First assign x coordinates, then y coordinates.
     branch(*this, xCoords, INT_VAR_NONE(), INT_VAL_MIN());
     //INT_VAR_NONE = Choose first unassigned value, from smaller to larger squares.
     //INT_VAL_MIN = Try to place from left to right, and top to bottom.
     branch(*this, yCoords, INT_VAR_NONE(), INT_VAL_MIN());
 }