151 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			151 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								Article: 5653 of comp.lang.prolog
							 | 
						||
| 
								 | 
							
								Newsgroups: comp.lang.prolog
							 | 
						||
| 
								 | 
							
								Path: ecrc!Germany.EU.net!mcsun!ub4b!news.cs.kuleuven.ac.be!bimbart
							 | 
						||
| 
								 | 
							
								From: bimbart@cs.kuleuven.ac.be (Bart Demoen)
							 | 
						||
| 
								 | 
							
								Subject: boolean constraint solvers
							 | 
						||
| 
								 | 
							
								Message-ID: <1992Oct19.093131.11399@cs.kuleuven.ac.be>
							 | 
						||
| 
								 | 
							
								Sender: news@cs.kuleuven.ac.be
							 | 
						||
| 
								 | 
							
								Nntp-Posting-Host: hera.cs.kuleuven.ac.be
							 | 
						||
| 
								 | 
							
								Organization: Dept. Computerwetenschappen K.U.Leuven
							 | 
						||
| 
								 | 
							
								Date: Mon, 19 Oct 1992 09:31:31 GMT
							 | 
						||
| 
								 | 
							
								Lines: 120
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									?- calc_constr(N,C,L) . % with N instantiated to a positive integer
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								generates in the variable C a datastructure that can be interpreted as a
							 | 
						||
| 
								 | 
							
								boolean expression (and in fact is so by SICStus Prolog's bool:sat) and in L
							 | 
						||
| 
								 | 
							
								the list of variables involved in this boolean expression; so
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									?- calc_constr(N,C,L) , bool:sat(C) , bool:labeling(L) .
							 | 
						||
| 
								 | 
							
											% with N instantiated to a positive integer
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								shows the instantiations of L for which the boolean expression is true
							 | 
						||
| 
								 | 
							
								e.g.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									| ?- calc_constr(3,C,L) , bool:sat(C) , bool:labeling(L) .
							 | 
						||
| 
								 | 
							
									% C = omitted
							 | 
						||
| 
								 | 
							
									L = [1,0,1,0,1,0,1,0,1] ? ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									no
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								it is related to a puzzle which I can describe if people are interested
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								SICStus Prolog can solve this puzzle up to N = 9  on my machine; it then
							 | 
						||
| 
								 | 
							
								fails because of lack of memory (my machine has relatively little: for N=9
							 | 
						||
| 
								 | 
							
								SICStus needs 14 Mb - and about 50 secs runtime + 20 secs for gc on Sparc 1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								I am interested in hearing about boolean constraint solvers that can deal with
							 | 
						||
| 
								 | 
							
								the expression generated by the program below, for large N and in reasonable
							 | 
						||
| 
								 | 
							
								time and space; say N in the range 10 to 20: the number of solutions for
							 | 
						||
| 
								 | 
							
								different N varies wildly; there is exactly one solution for N = 10,12,13,15,20
							 | 
						||
| 
								 | 
							
								but for N=18 or 19 there are several thousand, so perhaps it is best to
							 | 
						||
| 
								 | 
							
								restrict attention to N with only one solution - unless that is unfair to your
							 | 
						||
| 
								 | 
							
								solver
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								in case you have to adapt the expression for your own boolean solver, in
							 | 
						||
| 
								 | 
							
								the expression generated, ~ means negation, + means disjunction,
							 | 
						||
| 
								 | 
							
								* means conjunction and somewhere in the program, 1 means true
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Thanks
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Bart Demoen
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% test(N,L) :- calc_constr(N,C,L) , bool:sat(C) , bool:labeling(L) .
							 | 
						||
| 
								 | 
							
								test(N,L) :-   calc_constr(N,C,L) , solve_bool(C,1).
							 | 
						||
| 
								 | 
							
								testbl(N,L) :- calc_constr(N,C,L) , solve_bool(C,1), labeling.
							 | 
						||
| 
								 | 
							
								testul(N,L) :- calc_constr(N,C,L) , solve_bool(C,1), label_bool(L).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								calc_constr(N,C,L) :-
							 | 
						||
| 
								 | 
							
										M is N * N ,
							 | 
						||
| 
								 | 
							
										functor(B,b,M) ,
							 | 
						||
| 
								 | 
							
										B =.. [_|L] ,
							 | 
						||
| 
								 | 
							
										cc(N,N,N,B,C,1) .
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								cc(0,M,N,B,C,T) :- ! ,
							 | 
						||
| 
								 | 
							
										NewM is M - 1 ,
							 | 
						||
| 
								 | 
							
										cc(N,NewM,N,B,C,T) .
							 | 
						||
| 
								 | 
							
								cc(_,0,_,B,C,C) :- ! .
							 | 
						||
| 
								 | 
							
								cc(I,J,N,B,C,T) :-
							 | 
						||
| 
								 | 
							
										neighbours(I,J,N,B,C,S) ,
							 | 
						||
| 
								 | 
							
										NewI is I - 1 ,
							 | 
						||
| 
								 | 
							
										cc(NewI,J,N,B,S,T) .
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								neighbours(I,J,N,B,C,S) :-
							 | 
						||
| 
								 | 
							
										add(I,J,N,B,L,R1) ,
							 | 
						||
| 
								 | 
							
										add(I-1,J,N,B,R1,R2) ,
							 | 
						||
| 
								 | 
							
										add(I+1,J,N,B,R2,R3) ,
							 | 
						||
| 
								 | 
							
										add(I,J-1,N,B,R3,R4) ,
							 | 
						||
| 
								 | 
							
										add(I,J+1,N,B,R4,[]) ,	% L is the list of neighbours of (I,J)
							 | 
						||
| 
								 | 
							
													% including (I,J)
							 | 
						||
| 
								 | 
							
										odd(L,C,S) .
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								add(I,J,N,B,S,S) :- I =:= 0 , ! .
							 | 
						||
| 
								 | 
							
								add(I,J,N,B,S,S) :- J =:= 0 , ! .
							 | 
						||
| 
								 | 
							
								add(I,J,N,B,S,S) :- I > N , ! .
							 | 
						||
| 
								 | 
							
								add(I,J,N,B,S,S) :- J > N , ! .
							 | 
						||
| 
								 | 
							
								add(I,J,N,B,[X|S],S) :- A is (I-1) * N + J , arg(A,B,X) .
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% odd/2 generates the constraint that an odd number of elements of its first
							 | 
						||
| 
								 | 
							
								% argument must be 1, the rest must be 0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								odd(L,C*S,S):- exors(L,C).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  exors([X],X).
							 | 
						||
| 
								 | 
							
								  exors([X|L],X#R):- L=[_|_],
							 | 
						||
| 
								 | 
							
									exors(L,R).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								% did this by enumeration, because there are only 4 possibilities
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								odd([A],	A * S,S) :- ! .
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								odd([A,B,C],	((A * ~~(B) * ~~(C)) + 
							 | 
						||
| 
								 | 
							
										(A * B * C) + 
							 | 
						||
| 
								 | 
							
										( ~~(A) * B * ~~(C)) + 
							 | 
						||
| 
								 | 
							
										( ~~(A) * ~~(B) * C))  * S,S)
							 | 
						||
| 
								 | 
							
										:- ! .
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								odd([A,B,C,D],	((A * ~~(B) * ~~(C) * ~~(D)) +
							 | 
						||
| 
								 | 
							
										(A * B * C * ~~(D)) +
							 | 
						||
| 
								 | 
							
										(A * B * ~~(C) * D) +
							 | 
						||
| 
								 | 
							
										(A * ~~(B) * C * D) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * B * ~~(C) * ~~(D)) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * B * C * D) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * ~~(B) * C * ~~(D)) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * ~~(B) * ~~(C) * D))  * S,S )
							 | 
						||
| 
								 | 
							
										:- ! .
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								odd([A,B,C,D,E],((A * ~~(B) * ~~(C) * ~~(D) * ~~(E)) +
							 | 
						||
| 
								 | 
							
										(A * B * C * ~~(D) * ~~(E)) +
							 | 
						||
| 
								 | 
							
										(A * B * ~~(C) * D * ~~(E)) +
							 | 
						||
| 
								 | 
							
										(A * ~~(B) * C * D * ~~(E)) +
							 | 
						||
| 
								 | 
							
										(A * B * ~~(C) * ~~(D) * E) +
							 | 
						||
| 
								 | 
							
										(A * ~~(B) * C * ~~(D) * E) +
							 | 
						||
| 
								 | 
							
										(A * ~~(B) * ~~(C) * D * E) +
							 | 
						||
| 
								 | 
							
										(A * B * C * D * E) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * B * ~~(C) * ~~(D) * ~~(E)) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * B * ~~(C) * D * E) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * B * C * ~~(D) * E) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * B * C * D * ~~(E)) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * ~~(B) * C * ~~(D) * ~~(E)) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * ~~(B) * C * D * E) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * ~~(B) * ~~(C) * D * ~~(E)) +
							 | 
						||
| 
								 | 
							
										( ~~(A) * ~~(B) * ~~(C) * ~~(D) * E))  * S,S ) :- ! .
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |