Advertisement
Guest User

Untitled

a guest
Apr 26th, 2018
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.71 KB | None | 0 0
  1. 1 2 2 4 % top left corner 1 2 - bottom right corner 2 4
  2. 1 3 1 1 % top left corner 1 1 - bottom right corner 3 1
  3.  
  4. %% PROBLEM
  5. %
  6. % let P be a matrix whose elements are zeros and ones
  7. % find the best(*) combination of non-overlapping submatrices of P
  8. % so that each submatrix respect these properties:
  9. % - contains at least L zeros and L ones (min area=2*L)
  10. % - contains at most H elements (max area=H)
  11. %
  12. % (*) the best is the one which maximize the total number of elements in all the submatrices
  13. %
  14. % notices: the best combination could be not unique
  15. % is not always possibile to cover all the elements of P with the submatrices of the best combination
  16. %
  17. %% INPUT
  18. P=round(rand(8,8)); L=1; H=5;
  19. %P=dlmread('small.txt'); L=1; H=5; % small can be found here https://pastebin.com/RTc5L8We
  20. %P=dlmread('medium.txt'); L=2; H=8; % medium can be found here https://pastebin.com/qXJEiZTX
  21. %P=dlmread('big.txt'); L=4; H=12; % big can be found here https://pastebin.com/kBFFYg3K
  22. %P=[0 0 0 0 0 1;0 0 0 0 0 1;0 1 0 1 0 1;0 0 0 0 0 0;0 0 0 0 0 0]; L=1; H=6;
  23. P=[0 0 0 0 0;0 1 1 1 0;0 0 0 0 0]; L=1; H=6;
  24. %P=[1,0,0,0,0;1,1,1,1,1;1,0,0,0,0]; L=1; H=5;
  25.  
  26. %% FIND ALL THE SUBMATRICES OF AREA >= 2*L & <= H
  27. %
  28. % conv2(input_matrix,shape_matrix,'valid')
  29. % creates a matrix, where each element is the sum of all the elements contained in
  30. % the submatrix (contained in input_matrix and with the shape given by shape_matrix)
  31. % having its top left corner at said element
  32. %
  33. % ex. conv2([0,1,2;3,4,5;6,7,8],ones(2,2),'valid')
  34. % ans =
  35. % 8 12
  36. % 20 24
  37. % where 8=0+1+3+4 12=1+2+4+5 20=3+4+6+7 24=4+5+7+8
  38. %
  39. s=[]; % will contain the indexes and the area of each submatrix
  40. % i.e. 1 3 2 5 9 is the submatrix with area 9 and corners in 1 2 and in 3 5
  41. for sH = H:-1:2*L
  42. div_sH = divisors(sH);
  43. fprintf('_________AREA %d_________n',sH)
  44. for k = 1:length(div_sH)
  45. a = div_sH(k);
  46. b = div_sH(end-k+1);
  47. convP = conv2(P,ones(a,b),'valid');
  48. [i,j] = find((convP >= L) & (convP <= sH-L));
  49. if ~isempty([i,j])
  50. if size([i,j],1) ~= 1
  51. % rows columns area
  52. s = [s;[i,i-1+a , j,j-1+b , a*b*ones(numel(i),1)]];
  53. else
  54. s = [s;[i',i'-1+a,j',j'-1+b,a*b*ones(numel(i),1)]];
  55. end
  56. fprintf('[%dx%d] submatrices: %dn',a,b,size(s,1))
  57. end
  58. end
  59. end
  60. fprintf('n')
  61. s(:,6)=1:size(s,1);
  62.  
  63. %% FIND THE BEST COMBINATION
  64. tic
  65. [R,C]=size(P); % rows and columns of P
  66. no_ones=sum(P(:)); % counts how many ones are in P
  67. % a combination of submatrices cannot contain more than max_no_subm submatrices
  68. if no_ones <= R*C-no_ones
  69. max_no_subm=floor(no_ones/L);
  70. else
  71. max_no_subm=floor(R*C-no_ones/L);
  72. end
  73. comb(2,1)=R*C+1; % will contain the best combination
  74. s_copy=s; % save a copy of s
  75. [comb,perfect]=recursion(s,s_copy,comb,0,0,R,C,0,false,H,[],size(s,1),false,[0,0,0],0,0,0,0,0,0,max_no_subm);
  76. fprintf('ntime: %2.2fsnn',toc)
  77. if perfect
  78. disp('***********************************')
  79. disp('*** PERFECT COMBINATION FOUND ***')
  80. disp('***********************************')
  81. end
  82.  
  83. %% PRINT RESULTS
  84. if (R < 12 && C < 12)
  85. for i = 1:length(find(comb(2,3:end)))
  86. optimal_comb_slices(i,:)=s(comb(2,i+2),:);
  87. end
  88. optimal_comb_slices(:,1:5)
  89. P
  90. end
  91.  
  92. function [comb,perfect,counter,area,v,hold_on,ijk,printed,first_for_i,second_for_i,third_for_i] = recursion(s,s_copy,comb,counter,area,R,C,k,hold_on,H,v,size_s,perfect,ijk,size_s_ovrlppd,size_s_ovrlppd2,printed,third_for_i,second_for_i,first_for_i,max_no_subm)
  93. %
  94. % OUTPUT (that is actually going to be used in the main script)
  95. % comb [matrix] a matrix of two rows, the first one contains the current combination
  96. % the second row contains the best combination found
  97. % perfect [boolean] says if the combination found is perfect (a combination is perfect if
  98. % the submatrices cover all the elements in P and if it is made up with
  99. % the minimum number of submatrices possible)
  100. %
  101. % OUTPUT (only needed in the function itself)
  102. % counter [integer] int that keeps track of how many submatrices are in the current combination
  103. % area [integer] area covered with all the submatrices of the current combination
  104. % v [vector] keeps track of the for loops that are about to end
  105. % hold_on [boolean] helps v to remove submatrices from the current combination
  106. %
  107. % OUTPUT (only needed to print results)
  108. % ijk [vector] contains the indexes of the first three nested for loops (useful to see where the function is working)
  109. % printed [boolean] used to print text on different lines
  110. % first_for_i second_for_i third_for_i [integers] used by ijk
  111. %
  112. %
  113. % INPUT
  114. % s [matrix] the set of all the submatrices of P
  115. % s_copy [matrix] the set of all the submatrices that don't overlap the ones in the current combination
  116. % (is equal to s when the function is called for the first time)
  117. % R,C [integers] rows and columns of P
  118. % k [integer] area of the current submatrix
  119. % H [integer] maximum number of cells that a submatrix can contains
  120. % size_s [integer] number of rows of s i.e. number of submatrices in s
  121. % size_s_ovrlppd [integer] used by ijk
  122. % size_s_ovrlppd2 [integer] used by ijk
  123. % max_no_subm [integer] maximum number of submatrices contained in a combination
  124. %
  125. %
  126. % the function starts considering the first submatrix (call it sub1) in the set 's' of all the submatrices
  127. % and adds it to the combination
  128. % then it finds 's_ovrlppd' i.e. the set of all the submatrices that don't overlap sub1
  129. % and the function calls itself considering the first submatrix (call it sub2) in the set 's_ovrlppd'
  130. % and adds it to the combination
  131. % then it finds the set of all the submatrices that don't overlap sub2 and
  132. % so on until there are no more non-overlapping submatrices
  133. % then it replaces the last submatrix in the combination with the second one of the last set of non-overlapping
  134. % submatrices and saves the combination which covers more elements in P
  135. % and so on for all the submatrices of the set 's'
  136. %
  137. % DOWNSIDE OF THIS METHOD
  138. % if 's' contains thousands of submatrices, the function will create hundreds of nested for loops
  139. % so both time and space complexities can be really high and the computer might freeze
  140. %
  141. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  142. %%%% SAVE AND RESET COMBINATIONS %%%
  143. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  144. % s_copy is empty when no more submatrices can be added to the current
  145. % combination, in this case we have to check if this combination is
  146. % better the best combination previosly found, if so then we overwrite it
  147. %
  148. % then we have to remove one or more submatrices from the combination (depending on
  149. % how many nested for loops are about to be closed)
  150. % and compute another combination
  151. % to 'remove one or more submatrices from the combination' it is necessary to do these things:
  152. % - reduce the area
  153. % - reduce the combination
  154. % - reduce the counter
  155. %
  156. if isempty(s_copy)
  157. comb(1,2)=counter; % final no of submatrices in the combination
  158. comb(1,1)=R*C-area; % no. of cells remained in P after removing the cells contained in the submatrices of the combination
  159. % if the combination just found is better than the previous overwrite it
  160. if comb(1,1)<comb(2,1) || (comb(1,1)==comb(2,1) && comb(1,2)<comb(2,2))
  161. comb(2,:)=comb(1,:);
  162. disp(['[area_left] ', num2str(comb(2,1)), ' [slices] ', num2str(comb(2,2))])
  163. printed=true;
  164. end
  165.  
  166. area=area-k; % tot area of the combination excluding the last sumatrix
  167. if ~isempty(v) && ~hold_on % more than one submatrix must be removed
  168. i=size(v,2);
  169. if i>length(find(v)) % if v contains at least one 0
  170. while v(i)==1 % find the index of the last 0
  171. i=i-1;
  172. end
  173. last_i_counter=size(v(i+1:end),2); % no. of consecutive for loop that are about to end
  174. v=v(1:i-1);
  175. else
  176. last_i_counter=i;
  177. v=[];
  178. end
  179. for i=1:last_i_counter
  180. area=area-s(comb(1,2+counter-i),5); % reduce the area
  181. end
  182. comb(1,2+counter-last_i_counter:2+counter)=0; % remove submatrices from the combination
  183. counter=counter-(last_i_counter+1); % reduce the counter
  184. hold_on=true;
  185. else % exactly one submatrix must be removed
  186. comb(1,2+counter)=0;
  187. counter=counter-1;
  188. end
  189. % USED TO SHOW THAT WITHOUT s_ovrlppd(s_ovrlppd(:,6)<pos,:)=[]; THERE ARE
  190. % LOT OF REPEATING COMBINATIONS
  191. % if isempty(s_copy)
  192. % comb(size(comb,1)+1,:)=comb(1,:);
  193. % comb(size(comb,1),2)=counter; % final no of slices in the combination
  194. % comb(size(comb,1),1)=R*C-area; % no. of cells remained in P after removing the cells contained in the slices of the combination
  195. %
  196. % area=area-k;
  197. % if first_for_i == 34
  198. % comb(1:2,:)=[];
  199. % end
  200. % if ~isempty(v) && ~hold_on
  201. % i=size(v,2);
  202. % if i>length(find(v))
  203. % while v(i)==1
  204. % i=i-1;
  205. % end
  206. % last_i_counter=size(v(i+1:end),2);
  207. % v=v(1:i-1);
  208. % else
  209. % last_i_counter=i;
  210. % v=[];
  211. % end
  212. % for i=1:last_i_counter
  213. % area=area-s(comb(1,2+counter-i),5);
  214. % end
  215. % comb(1,2+counter-last_i_counter:2+counter)=0;
  216. % counter=counter-(last_i_counter+1);
  217. % hold_on=true;
  218. % else
  219. % comb(1,2+counter)=0;
  220. % counter=counter-1;
  221. % end
  222. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  223. %%% FIND COMBINATIONS %%%
  224. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  225. else
  226. for i = 1:size(s_copy,1) % fix the i-th submatrix
  227.  
  228. % if the combination cover all elements of P & the no. of submatrices is the minimum possibile
  229. if comb(2,1)==0 && comb(2,2)==ceil(R*C/H)
  230. perfect=true;
  231. return
  232. end
  233.  
  234. pos=s_copy(i,6); % position of current submatrix in s
  235. comb(1,3+counter)=pos; % add the position to the combination
  236. k=s(pos,5); % save the area of the current submatrix
  237. area=area+k; % area covered with all the submatrices of the combination up now
  238. counter=counter+1;
  239.  
  240. % if the area in P covered by the current combination could not
  241. % be bigger than the best combination found up now, then discard
  242. % the current combination and consider the next one
  243. if R*C-area-(max_no_subm-counter)*H > comb(2,1) && i < size(s_copy,1)
  244. % R*C-area-(max_no_subm-counter)*H can be negative if ceil(R*C/H) < max_no_subm
  245. counter=counter-1;
  246. comb(1,3+counter)=0;
  247. area=area-k;
  248. else
  249. s_ovrlppd=s_copy; % initializing the set of non-overlapping submatrices
  250. s_ovrlppd(s_copy(:,1)<=s_copy(i,2) & s_copy(:,2)>=s_copy(i,1) & s_copy(:,3)<=s_copy(i,4) & s_copy(:,4)>=s_copy(i,3),:)=[]; % delete submatrices that overlap the i-th one
  251. s_ovrlppd(s_ovrlppd(:,6)<pos,:)=[]; % remove submatrices that will generate combinations already studied
  252. % KEEP TRACK OF THE NESTED 'FOR' LOOPS ENDS REACHED
  253. if i==size(s_copy,1) % if i is the last cycle of the current for loop
  254. v(size(v,2)+1)=1; % a 1 means that the code entered the last i of a 'for' loop
  255. if size(s_ovrlppd,1)~=0 % hold on until an empty s_ovrlppd is found
  256. hold_on=true;
  257. else
  258. hold_on=false;
  259. end
  260. elseif ~isempty(v) && size(s_ovrlppd,1)~=0
  261. v(size(v,2)+1)=0; % a 0 means that s_ovrlppd in the last i of a 'for' loop is not empty => a new 'for' loop is created
  262. end
  263. %%%%%%%%%%%%%%%%%%%%%%%%
  264. %%% PRINT STATUS %%%
  265. %%%%%%%%%%%%%%%%%%%%%%%%
  266. if size(s_copy,1)==size_s
  267. ijk(1)=i;
  268. ijk(2:3)=0;
  269. % if ~printed && i~=1
  270. % fprintf(repmat('b',1,numel(num2str(first_for_i))+numel(num2str(second_for_i))+numel(num2str(third_for_i))+2+2+1)) % [] ,, return
  271. % else
  272. % printed=false;
  273. % end
  274. fprintf('[%d,%d,%d]n',ijk)
  275. size_s_ovrlppd=size(s_ovrlppd,1);
  276. first_for_i=i;
  277. second_for_i=0;
  278. elseif size(s_copy,1)==size_s_ovrlppd
  279. ijk(2)=i;
  280. ijk(3)=0;
  281. if ~printed
  282. fprintf(repmat('b',1,numel(num2str(first_for_i))+numel(num2str(second_for_i))+numel(num2str(third_for_i))+2+2+1)) % [] ,, return
  283. else
  284. printed=false;
  285. end
  286. fprintf('[%d,%d,%d]n',ijk)
  287. size_s_ovrlppd2=size(s_ovrlppd,1);
  288. second_for_i=i;
  289. third_for_i=0;
  290. elseif size(s_copy,1)==size_s_ovrlppd2
  291. ijk(3)=i;
  292. if ~printed
  293. fprintf(repmat('b',1,numel(num2str(first_for_i))+numel(num2str(second_for_i))+numel(num2str(third_for_i))+2+2+1))
  294. else
  295. printed=false;
  296. end
  297. fprintf('[%d,%d,%d]n',ijk)
  298. third_for_i=i;
  299. end
  300. [comb,perfect,counter,area,v,hold_on,ijk,printed,first_for_i,second_for_i,third_for_i]=recursion(s,s_ovrlppd,comb,counter,area,R,C,k,hold_on,H,v,size_s,perfect,ijk,size_s_ovrlppd,size_s_ovrlppd2,printed,third_for_i,second_for_i,first_for_i,max_no_subm);
  301. end
  302. end
  303. end
  304. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement