Advertisement
JosepRivaille

LI - Packing

Jun 23rd, 2017
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Prolog 6.31 KB | None | 0 0
  1. :-include(entradaPacking5).
  2. :-dynamic(varNumber/3).
  3. symbolicOutput(0). % set to 1 to see symbolic output only; 0 otherwise.
  4.  
  5. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  7.  
  8. %% We are given a large rectangular piece of cloth from which we want
  9. %% to cut a set of smaller rectangular pieces. The goal of this problem
  10. %% is to decide how to cut those small pieces from the large cloth, i.e.
  11. %% how to place them.
  12. %%
  13. %% Note 1: The smaller pieces cannot be rotated.
  14. %%
  15. %% Note 2: All dimensions are integer numbers and are given in
  16. %% meters. Additionally, the larger piece of cloth is divided into
  17. %% square cells of dimension 1m x 1m, and every small piece must
  18. %% obtained exactly by choosing some of these cells
  19. %%
  20. %% Extend this file to do this using a SAT solver, following the
  21. %% example of sudoku.pl:
  22. %% - implement writeClauses so that it computes the solution, and
  23. %% - implement displaySol so that it outputs the solution in the
  24. %%   format shown in entradapacking5.pl.
  25.  
  26. %%%%%% Some helpful definitions to make the code cleaner:
  27. rect(B):-rect(B,_,_).
  28. xCoord(X) :- width(W),  between(1,W,X).
  29. yCoord(Y) :- height(H), between(1,H,Y).
  30. width(B,W):- rect(B,W,_).
  31. height(B,H):- rect(B,_,H).
  32. insideTable(X,Y):- width(W), height(H), between(1,W,X), between(1,H,Y).
  33.  
  34. %%%%%%  Variables: They might be useful
  35. % starts-B-X-Y:   box B has its left-bottom cell with upper-right coordinates (X,Y)
  36. %  fills-B-X-Y:   box B fills cell with upper-right coordinates (X,Y)
  37.  
  38. writeClauses:- setPiece, fillsBoard, noOverlapping.
  39.  
  40. setPiece :- rect(B), findall(starts-B-X-Y, fitsBoard(B, X, Y), L), exactly(1, L), fail.
  41. setPiece. % Force true eval.
  42.  
  43. fitsBoard(B, X1, Y1) :- rect(B, W, H), insideTable(X1, Y1), X2 is X1+W-1, Y2 is Y1+H-1, insideTable(X2, Y2).
  44.  
  45. fillsBoard :-
  46.     rect(B, W, H), fitsBoard(B, X1, Y1),
  47.     X2 is X1+W-1, Y2 is Y1+H-1,
  48.     between(X1, X2, XC), between(Y1, Y2, YC),
  49.     writeClause([\+starts-B-X1-Y1, fills-B-XC-YC]), fail.
  50. fillsBoard.
  51.  
  52. noOverlapping :- rect(B1), rect(B2), B1\=B2, insideTable(X, Y), atMost(1, [fills-B1-X-Y, fills-B2-X-Y]), fail.
  53. noOverlapping.
  54.  
  55. %%%%%%%%%%%%%%%%%%%%%%%
  56. %%%%%% show the solution. Here M contains the literals that are true in the model:
  57.  
  58. displaySol(M):-
  59.     yCoord(Y1), height(H),
  60.     Y2 is H-Y1+1, nl, xCoord(X),
  61.     member(fills-B-X-Y2, M), writeNumber(B), fail.
  62. displaySol(_).
  63.  
  64. writeNumber(B):- B < 10, write(" ").
  65. writeNumber(B):- write(B), write(" ").
  66.  
  67. %%%%%%%%%%%%%%%%%%%%%%%%%%%
  68.  
  69. % Express that Var is equivalent to the disjunction of Lits:
  70. expressOr( Var, Lits ):- member(Lit,Lits), negate(Lit,NLit), writeClause([ NLit, Var ]), fail.
  71. expressOr( Var, Lits ):- negate(Var,NVar), writeClause([ NVar | Lits ]),!.
  72.  
  73.  
  74. %%%%%% Cardinality constraints on arbitrary sets of literals Lits:
  75.  
  76. exactly(K,Lits):- atLeast(K,Lits), atMost(K,Lits),!.
  77.  
  78. atMost(K,Lits):-   % l1+...+ln <= k:  in all subsets of size k+1, at least one is false:
  79.     negateAll(Lits,NLits),
  80.     K1 is K+1,    subsetOfSize(K1,NLits,Clause), writeClause(Clause),fail.
  81. atMost(_,_).
  82.  
  83. atLeast(K,Lits):-  % l1+...+ln >= k: in all subsets of size n-k+1, at least one is true:
  84.     length(Lits,N),
  85.     K1 is N-K+1,  subsetOfSize(K1, Lits,Clause), writeClause(Clause),fail.
  86. atLeast(_,_).
  87.  
  88. negateAll( [], [] ).
  89. negateAll( [Lit|Lits], [NLit|NLits] ):- negate(Lit,NLit), negateAll( Lits, NLits ),!.
  90.  
  91. negate(\+Lit,  Lit):-!.
  92. negate(  Lit,\+Lit):-!.
  93.  
  94. subsetOfSize(0,_,[]):-!.
  95. subsetOfSize(N,[X|L],[X|S]):- N1 is N-1, length(L,Leng), Leng>=N1, subsetOfSize(N1,L,S).
  96. subsetOfSize(N,[_|L],   S ):-            length(L,Leng), Leng>=N,  subsetOfSize( N,L,S).
  97.  
  98.  
  99. %%%%%% main:
  100.  
  101. main:- symbolicOutput(1), !, writeClauses, halt.   % print the clauses in symbolic form and halt
  102. main:-
  103.     initClauseGeneration,
  104.     tell(clauses), writeClauses, told,          % generate the (numeric) SAT clauses and call the solver
  105.     tell(header), writeHeader, told,
  106.     numVars(N), numClauses(C),
  107.     write('Generated '), write(C), write(' clauses over '), write(N), write(' variables. '),nl,
  108.     shell('cat header clauses > infile.cnf',_),
  109.     write('Calling solver....'), nl,
  110.     shell('picosat -v -o model infile.cnf', Result),  % if sat: Result=10; if unsat: Result=20.
  111.     treatResult(Result),!.
  112.  
  113. treatResult(20):- write('Unsatisfiable'), nl, halt.
  114. treatResult(10):- write('Solution found: '), nl, see(model), symbolicModel(M), seen, displaySol(M), nl,nl,halt.
  115.  
  116. initClauseGeneration:-  %initialize all info about variables and clauses:
  117.     retractall(numClauses(   _)),
  118.     retractall(numVars(      _)),
  119.     retractall(varNumber(_,_,_)),
  120.     assert(numClauses( 0 )),
  121.     assert(numVars(    0 )),     !.
  122.  
  123. writeClause([]):- symbolicOutput(1),!, nl.
  124. writeClause([]):- countClause, write(0), nl.
  125. writeClause([Lit|C]):- w(Lit), writeClause(C),!.
  126. w( Lit ):- symbolicOutput(1), write(Lit), write(' '),!.
  127. w(\+Var):- var2num(Var,N), write(-), write(N), write(' '),!.
  128. w(  Var):- var2num(Var,N),           write(N), write(' '),!.
  129.  
  130.  
  131. % given the symbolic variable V, find its variable number N in the SAT solver:
  132. var2num(V,N):- hash_term(V,Key), existsOrCreate(V,Key,N),!.
  133. existsOrCreate(V,Key,N):- varNumber(Key,V,N),!.                            % V already existed with num N
  134. existsOrCreate(V,Key,N):- newVarNumber(N), assert(varNumber(Key,V,N)), !.  % otherwise, introduce new N for V
  135.  
  136. writeHeader:- numVars(N),numClauses(C), write('p cnf '),write(N), write(' '),write(C),nl.
  137.  
  138. countClause:-     retract( numClauses(N0) ), N is N0+1, assert( numClauses(N) ),!.
  139. newVarNumber(N):- retract( numVars(   N0) ), N is N0+1, assert(    numVars(N) ),!.
  140.  
  141. % Getting the symbolic model M from the output file:
  142. symbolicModel(M):- get_code(Char), readWord(Char,W), symbolicModel(M1), addIfPositiveInt(W,M1,M),!.
  143. symbolicModel([]).
  144. addIfPositiveInt(W,L,[Var|L]):- W = [C|_], between(48,57,C), number_codes(N,W), N>0, varNumber(_,Var,N),!.
  145. addIfPositiveInt(_,L,L).
  146. readWord(99,W):- repeat, get_code(Ch), member(Ch,[-1,10]), !, get_code(Ch1), readWord(Ch1,W),!. % skip line starting w/ c
  147. readWord(115,W):- repeat, get_code(Ch), member(Ch,[-1,10]), !, get_code(Ch1), readWord(Ch1,W),!. % skip line starting w/ s
  148. readWord(-1,_):-!, fail. %end of file
  149. readWord(C,[]):- member(C,[10,32]), !. % newline or white space marks end of word
  150. readWord(Char,[Char|W]):- get_code(Char1), readWord(Char1,W), !.
  151. %========================================================================================
  152.  
  153. % JosepRivaille
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement