Packing Squares into A Rectangle, Using Constraints (CLINGO) - answer-set-programming

Use CLINGO to pack a given set of squares into a given rectangular area without overlaps.
For example, we want to pack the squares:
A of size 4, B of size 3, C & D of size 2, E of size 1
into an area 5 x 8.
#const x = 8.
#const y = 5.
square(a,4; b,3; c,2; d,2; e,1).
%generate a grid:
1 { pos(X,Y) } 1 :- x(X), y(Y).
%generate placement of the squares
1 { placement(P, SQ) } 1 :- square(SQ), pos(P).
%throw out overlaps
I'm not sure what the constraint to throwing out overlapping squares would be, or if I'm doing this right.

Fix the code
The grid generation does not yield expected atoms. Here is the one you want:
pos(1..x,1..y).
Also, the placement of squares says: placement/2 holds for any pair square×position. Instead, we want to associate a position to each square:
1 {placement(pos(X,Y),S): pos(X,Y)} 1:- square(S,_).
Now we have to design the overlapping constraints.
Solution to the problem.
First, we define occupy/3, where occupy(S,X,Y) holds when square S occupy the grid at position (X,Y):
occupy(S,X+I,Y+J):- square(S,Size) ; placement(pos(X,Y),S) ; I=0..Size-1 ; J=0..Size-1.
For instance, square(a,2). placement(a,pos(1,3)). will be associated with occupy(a,1,3).occupy(a,1,4).occupy(a,2,3).occupy(a,2,4)..
Then, we discard any model that have more than more than one occupy at a given position:
:- {occupy(_,X,Y)}>1 ; occupy(_,X,Y).
Fix: you must also discard models where a square is placed so it occupy a non existing place:
:- occupy(_,X,Y) ; not pos(X,Y).

Related

In MATLAB, how to create all the possible Sub-Matrices from a large Matrix by shifting exactly one row and one column?

Suppose i have a 256*256 matrix(image pixel values).I want to create that Sliding window 1 to Sliding Window n by shifting exactly one row and one column. All the Sliding Window Matrix Should be in the size of 5*5.
I have tried with this following code. By this i am getting the submatrices but not by the shifting of exactly one row and one column.
I = imread('D:\Study Material\project\Finger Print Database\1_2.png');
J = imresize(I, [128 128]);
C=mat2tiles(J,[5,5]);
Suppose original matrix has 10 row and 10 column.
I'm getting the sub-matrices like (column1-column5 & row1-row5) then (column6-column10 & row6-row10).
But I need like this- (column1-column5 & row1-row5)then (column2-column6 & row1-row5)like this first column will be shifted to 10. After that row will be shifted to 10.
You need im2col with the 'sliding' option, followed by reshape:
blockSize = [5 5];
C = reshape(im2col(J, blockSize, 'sliding'), blockSize(1), blockSize(2), []);

How to use logical indexing instead of for loops for mapping interpolated image values?

My program transforms an original equirectangular image into an azimuthal orthographic projection.
This is done by locating every pixel on the projection image (destination) on the equirectangular image (input). Since the positions on the equirectangular image are often non inter numbers because of the projection (trigonomical and other functions) the color values of the projection images pixels have to be interpolated from the color values of the source image.
im_source is a 3 dimensional matrix, ordered by (row, column, color_channel), containing the value of the particular color channel
m_source_q is a 2 dimensional matrix, containing the row of the interpolation (query) grid, so for a 1024*512 original image and a grid precision of 0.1 pixels m_source_q looks like:
[1 1 1 1 .... 1
1.1 1.1 1.1 1.1 .... 1.1
1.2 1.2 1.2 1.2 ..... 1.2
...
512 512 512 512 .... 512]
n_source_q likewise contains the query column position
[1 1.1 1.2 1.3 .... 1024
1 1.1 1.2 1.3 .... 1024
...
1 1.1 1.2 1.3 .... 1024]
p_er is a 3-D matrix. it is a two-dimensional map that contains the fractioned coordinates of the interpolated original image for every pixel on the projection image. so for example p_er(502, 262, 1) == 259.9 (corresponding row in original image); p_er(592, 252, 2) == 513.2 (corresponding column in original image).
imq is a 3-D matrix that contains all interpolated color values for every color channel and for every grid position. imq is obtained by interpolation:
for idim=1:3
imq(:,:,idim) = interp2(n_source, m_source, imsource(:,:,idim), n_source_q, m_source_q, 'linear');
end;
note that idim is the index of the color channel (R: 1, G: 2, B: 3)
imp_double is a 3-D matrix that contains the (double type / real number) color values of all color channels for every projection image pixel. this
will just be converted to projection_image = uint8(imp_double).
The last step is mapping the projections pixels to the corresponding interpolated color values:
for idim=1:3
imq_idim = imq(:,:,idim);
for m=1:Hp % Hp .. height of projection image
for n=1:Wp % Wp .. width of projection image
if isRealPixel(m,n)
imp_double(m,n,idim)=imq_idim(m_source_q==per(m,n,1) & n_source_q==per(m,n,2));
end;
end;
end;
end;
This works, but it takes really too long, and I'm pretty sure that the two nested for loops are the cause of this.
My question: How can I avoid the for loops by logical indexing, or by some other method?
I tried
for idim=1:3
imp_double(:,:,idim) = imq_idim(m_source_q==per(:,:,1) & n_source_q==per(:,:,2));
end;
but the interpreter complains the sizes of the matrices don't match. Apparently I have to tell MATLAB over what index vector (is that how you call it?) the function should be applied and the two colons are not sufficient. Do I need the matrices m_source and n_source, which are just the real source images row, rsp. col positions, for that purpose?
Return indices of matrix A that match an item in matrix B
out = ismember(A,B);
out in this case will have the shape of A, and contains only items that are in both A and B.
Partial Solution
This assumes imq_idim is the same size as m_source. If that's not the case and per(:,:,1) is the same size as img_idim then flip the arguments.
This also assumes that what you are trying to do is find any m_source values that are in per(:,:,1). If you are not trying to do this, then you also need to look at your looped solution, because that is what is currently happening there
for idim=1:3
imp_double(:,:,idim) = imq_idim(ismember(m_source_q,per(:,:,1)) & ....
ismember(n_source_q,per(:,:,2));
end;
Dimension Mismatch
The above code is correct on the right-side but won't pass to the left-side correctly in imp_double(:,:,idim) = ... %
Left-side
imp_double(:,:,idim) is asking for a matrix that is the same size as the first two dimensions of imp_double.
Right-side
imq_idim(ismember(m_source_q,per(:,:,1)) & ... ismember(n_source_q,per(:,:,2)); returns a one-dimensional, variable sized vector (depends on how many matches we get).
Solution
a) Make the right-side a matrix imp_double(:,:,idim) but with correct values changed
% imp_double MUST BE PREALLOCATED
temp = imp_double(:,:,idim); % temp is a 2D matrix
temp(ismember(m_source_q,per(:,:,1)) & ....
ismember(n_source_q,per(:,:,2))) = ...
imq_idim(ismember(m_source_q,per(:,:,1)) & ....
ismember(n_source_q,per(:,:,2)));
imp_double(:,:,idim) == temp;
b) Specify the indices to be changed in imp_double
This would be the easy solution with something like the below. The problem is, you can't index a 3D matrix with a 2D logical followed by a 3rd index. Any solution here will be redundant with a) but slightly more complicated
% Doesn't work because can't index imp_double(mat,ind)
imp_double(ismember(m_source_q,per(:,:,1)) & ....
ismember(n_source_q,per(:,:,2)),...
idim)) = ...
imp_double(:,:,idim) = imq_idim(ismember(m_source_q,per(:,:,1)) & ....
ismember(n_source_q,per(:,:,2));

Calculating the Local Ternary Pattern of an image?

I am calculating the Local Ternary Pattern of an image. My code is given below. Am I going in the right direction or not?
function [ I3 ] = LTP(I2)
m=size(I2,1);
n=size(I2,2);
for i=2:m-1
for j=2:n-1
J0=I2(i,j);
I3(i-1,j-1)=I2(i-1,j-1)>J0;
end
end
I2 is the image LTP is applied to.
This isn't quite correct. Here's an example of LTP given a 3 x 3 image patch and a threshold t:
(source: hindawi.com)
The range that you assign a pixel in a window to 0 is when the threshold is between c - t and c + t, where c is the centre intensity of the pixel. Therefore, because the intensity is 34 in the centre of this window, the range is between [29,39]. Any values that are beyond 39 get assigned 1 and any values that are below 29 get assigned -1. Once you determine the ternary codes, you split up the codes into upper and lower patterns. Basically, any values that get assigned a -1 get assigned 0 for upper patterns and any values that get assigned a -1 get assigned 1 for lower patterns. Also, for the lower pattern, any values that are 1 from the original window get mapped to 0. The final pattern is reading the bit pattern starting from the east location with respect to the centre (row 2, column 3), then going around counter-clockwise. Therefore, you should probably modify your function so that you're outputting both lower patterns and upper patterns in your image.
Let's write the corrected version of your code. Bear in mind that I will not give an optimized version. Let's get a basic algorithm working, and it'll be up to you on how you want to optimize this. As such, change your code to something like this, bearing in mind all of the stuff I talked about above. BTW, your function is not defined properly. You can't use spaces to define your function, as well as your variables. It will interpret each word in between spaces as variables or functions, and that's not what you want. Assuming your neighbourhood size is 3 x 3 and your image is grayscale, try something like this:
function [ ltp_upper, ltp_lower ] = LTP(im, t)
%// Get the dimensions
rows=size(im,1);
cols=size(im,2);
%// Reordering vector - Essentially for getting binary strings
reorder_vector = [8 7 4 1 2 3 6 9];
%// For the upper and lower LTP patterns
ltp_upper = zeros(size(im));
ltp_lower = zeros(size(im));
%// For each pixel in our image, ignoring the borders...
for row = 2 : rows - 1
for col = 2 : cols - 1
cen = im(row,col); %// Get centre
%// Get neighbourhood - cast to double for better precision
pixels = double(im(row-1:row+1,col-1:col+1));
%// Get ranges and determine LTP
out_LTP = zeros(3, 3);
low = cen - t;
high = cen + t;
out_LTP(pixels < low) = -1;
out_LTP(pixels > high) = 1;
out_LTP(pixels >= low & pixels <= high) = 0;
%// Get upper and lower patterns
upper = out_LTP;
upper(upper == -1) = 0;
upper = upper(reorder_vector);
lower = out_LTP;
lower(lower == 1) = 0;
lower(lower == -1) = 1;
lower = lower(reorder_vector);
%// Convert to a binary character string, then use bin2dec
%// to get the decimal representation
upper_bitstring = char(48 + upper);
ltp_upper(row,col) = bin2dec(upper_bitstring);
lower_bitstring = char(48 + lower);
ltp_lower(row,col) = bin2dec(lower_bitstring);
end
end
Let's go through this code slowly. First, I get the dimensions of the image so I can iterate over each pixel. Also, bear in mind that I'm assuming that the image is grayscale. Once I do this, I allocate space to store the upper and lower LTP patterns per pixel in our image as we will need to output this to the user. I have decided to ignore the border pixels where when we consider a pixel neighbourhood, if the window goes out of bounds, we ignore these locations.
Now, for each valid pixel that is within the valid borders of the image, we extract our pixel neighbourhood. I convert these to double precision to allow for negative differences, as well as for better precision. I then calculate the low and high ranges, then create a LTP pattern following the guidelines we talked about above.
Once I calculate the LTP pattern, I create two versions of the LTP pattern, upper and lower where any values of -1 for the upper pattern get mapped to 0 and 1 for the lower pattern. Also, for the lower pattern, any values that were 1 from the original window get mapped to 0. After, this, I extract out the bits in the order that I laid out - starting from the east, go counter-clockwise. That's the purpose of the reorder_vector as this will allow us to extract those exact locations. These locations will now become a 1D vector.
This 1D vector is important, as we now need to convert this vector into character string so that we can use bin2dec to convert the value into a decimal number. These numbers for the upper and lower LTPs are what are finally used for the output, and we place those in the corresponding positions of both output variables.
This code is untested, so it'll be up to you to debug this if it doesn't work to your specifications.
Good luck!

Matlab im2col function

This is a bit more of a general question, but, no matter how many times I read the description of MATLAB's im2col function, I cannot fully understand it. I need it for the computational efficiency because MATLAB is awful with nested for loops. Here's what I'm attempting to do, but using nested for loops:
[TRIMMED]=TM_FILTER(IMAGE, FILTER_SIZE, PERCENT)
Takes a 2-D array and returns the array, filtered with a
square trimed mean filter with length/width equal to FILTER_SIZE and percent equal to PERCENT.
%}
function [trimmed]=tm_filter(image, filter_size, percent)
if rem(filter_size, 2)==0 %make sure filter has a center pixel
error('filter size must be odd numbered'); %error and return if number is odd
return
end
if percent > 100 || percent < 0
error('Percentage must be ? [0, 100]');
return
end
[rows, columns]=size(image); %figure out pixels needed
n=(filter_size-1)/2; %n is pixel distance from center pixel to boundaries
padded=(padarray(image, [n,n],128)); %padding on boundaries so center pixel always has neighborhood
for i=1+n:rows %rows from first non-padded entry to last nonpadded entry
for j=1+n:columns %colums from first non-padded entry to last nonpadded entry
subimage=padded(i-n:i+n,j-n:j+n); %neighborhood same size as filter
average=trimmean(trimmean(subimage, percent), percent); %computes trimmed mean of neighborhood as trimmed mean of vector of trimmed means
trimmed(i-n, j-n)=average; %stores averaged pixel in new array
end
end
trimmed=uint8(trimmed); %converts image to gray levels from 0-255
Here is the code you want: note the entire nested loop was replaced with a single statement.
[TRIMMED]=TM_FILTER(IMAGE, FILTER_SIZE, PERCENT)
Takes a 2-D array and returns the array, filtered with a
square trimed mean filter with length/width equal to FILTER_SIZE and percent equal to PERCENT.
%}
function [trimmed]=tm_filter(image, filter_size, percent)
if rem(filter_size, 2)==0 %make sure filter has a center pixel
error('filter size must be odd numbered'); %error and return if number is odd
return
end
if percent > 100 || percent < 0
error('Percentage must be ? [0, 100]');
return
end
trimmed = (uint8)trimmean(im2col(image, filter_size), percent);
Explanation:
the im2col function turns each region of filter_size into a column. Your trimmean function can then operate on each of the regions (columns) in a single operation - much more efficient than extracting each shape in turn. Also note this requires only a single application of trimmean - in your original you first do it on the columns, then again on the rows, which will actually cause a more severe trim than I think you intended (exclude 50% first time, then 50% again - feels like excluding 75%. Not exactly true but you get my point). Also you will find that changing the order of operations (row, then column vs column, then row) would change the result because the filter is nonlinear.
For example
im = reshape(1:9, [3 3]);
disp(im2col(im,[2 2])
results in
1 2 4 5
2 3 5 6
4 5 7 8
5 6 8 9
since you took each of the 4 possible blocks of 2x2 from this matrix:
1 4 7
2 5 8
3 6 9
and turned them into columns
Note - with this technique (applied to the unpadded image) you do lose some pixels on the edge; your method added some padding so that every pixel (even ones on the edge) has a complete neighborhood, and as such the filter returns an image that is the same size as the original (but it's not clear what the effect of padding/filtering will be near the margin, and especially the corner: you have almost 75% percent of pixels fixed at 128 and that is likely to dominate the behavior in the corner).
why im2col? why not nlfilter?
>> trimmed = nlfilter( image, [filter_size filter_size],...
#(x) treimmean( trimmean(x, percent), percent ) );
Are you sure you process the entire image?
i and j only goes up to rows and columns respectively. However, when you update trimmed you access i-n and j-n. What about the last n rows and columns?
Why do you apply trimmean twice for each block? Isn't it more appropriate to process the block at once, as in trimmean( x(:), percent)?
I believe the results of trimmean( trimmean(x, percent), percent) will be different than those of trimmean( x(:), percent). Have you give it a thought?
A small remark, it is best not to use i and j as variable names in matlab.

Find row numbers in a binary array with a certain code

I'm building a program that plays Connect 4, and one of the things to check for is cases where your opponent has the following board positions:
[0,1,1,0,0] or [0,1,0,1,0] or [0,0,1,1,0]
where your opponent is one move away from having three pieces in a row with a blank on either side. If you don't fill one of the middle elements on your next move, your opponent can go there and force a checkmate.
What I have is a board of 42 squares, numbered 1:42. And I created a matrix called FiveCheck, where each row maps to five consecutive board positions. For example:
FiveCheck(34,:) = [board(7),board(14),board(21),board(28),board(35)];
FiveCheck(35,:) = [board(14),board(21),board(28),board(35),board(42)];
are two of the diagonals of the board.
I can test for the possible checkmate with
(sum(FiveCheck(:,2:4),2) == 2 + sum(FiveCheck,2) == 2) == 2
And that gives me a vector with 1's indicating that the corresponding FiveCheck row has a possible checkmate. Let's say the 34th element of that vector has a 1, and the pattern for that diagonal (from the example given above) is [0,0,1,1,0]. How do I return 14, the board position I should move to?
Another separate example, if the 35th element of that vector has a 1, and the pattern for that diagonal is [0,1,0,1,0], how do I return 28?
EDIT: I just realized this is impossible without some sort of a map. So I created FiveMap, a matrix the same size of FiveCheck, with the same formulas except the word "board" is removed. For example:
FiveMap(34,:) = [(7),(14),(21),(28),(35)];
FiveMap(35,:) = [(14),(21),(28),(35),(42)];
Since you are dealing with binary vectors of size 5, a very efficient solution might be the use of a look up table.
Consider board to be a binary matrix. you can filter it with 4 filters (of length 5), representing horizontal, vertical and two diagonals to identify possible positions you are looking for. Then, for specious locations, you can extract the 5 binary bits and use a look up table of size 32 to get the offset to the position where you should place your piece.
a small example:
% construct LUT
LUT = zeros(32,2); % dx and dy offsets for each entry
LUT(12,:) = [ 1 0 ]; % covering the case [0 1 1 0 0] - put piece 1 to the right of center
% continue constructing LUT here...
horFilt = ones(1, 5);
resp = imfilter( board, horFilt ); % need to think about board''s boundaries here...
[yy xx] = find( resp == 2 ); all locations where filter caught 2 out of 5
pat = board( yy, xx + [ -2 1 0 1 2] ); % I assume here only one location was found
pat = bin2dec( '0'+char( pat ) ); % convert binary pattern to decimal entry
board( yy + LUT(pat,2) , xx + LUT(pat, 1) ) = ... ; % your move here...