Download
/*
 * SICSTUS CLPFD DEMONSTRATION PROGRAM
 * Purpose   : Balanced Incomplete Block Design
 * Author    : Mats Carlsson
 *
 * The goal is to find a VxB binary matrix with
 * R ones in each row, K ones in each column,
 * the scalar product of any two rows being Lambda.
 *
 * | ?- bibd([rl,up,lex], 10, 90, 27, 3, 6).
 * | ?- bibd([rl,up,lex], 15, 70, 14, 3, 2).
 * | ?- bibd([rl,up,lex], 12, 88, 22, 3, 4).
 * | ?- bibd([rl,up,lex], 9, 120, 40, 3, 10).
 * | ?- bibd([rl,up,lex], 10, 120, 36, 3, 8).
 * | ?- bibd([rl,up,lex], 13, 104, 24, 3, 4).
*/

:- module(bibd, [bibd/6]).

:- use_module(library(lists)).
:- use_module(library(clpfd)).

bibd([Order,Lab,Lex], V, B, R, K, Lambda) :-
	bibd(Lex, V, B, R, K, Lambda, _Cells, Rows),
	bibd_order(Order, Rows, Vars),
	labeling([Lab], Vars),
	(   foreach(Row,Rows)
	do  (   foreach(R1,Row),
		foreach(S,String)
	    do  S is R1+"0"
	    ),
	    format('~s\n', [String])
	).

bibd_order(lr, Rows, Vars) :-
	(   foreach(Row,Rows),
	    fromto(Vars,S0,S,[])
	do  append(Row, S, S0)
	).
bibd_order(rl, Rows, Vars) :-
	(   foreach(Row,Rows),
	    fromto(Vars,S0,S,[])
	do  reverse(Row, Rev),
	    append(Rev, S, S0)
	).

bibd(Lex, V, B, R, K, Lambda, Cells, Rows) :-
	VC is V*B,
	length(Cells, VC),
	domain(Cells, 0, 1),
	(   fromto(Cells,C1,C3,[]),
	    foreach(Row1,Rows),
	    param(B)
	do  length(Row1, B),
	    (   foreach(Elt,Row1),
		fromto(C1,[Elt|C2],C2,C3)
	    do  true
	    )
	),
	transpose(Rows, Columns),
	(   Lex==lex ->
	    Rows = LexRows,
	    Columns = LexColumns
	;   reverse(Rows, LexRows),
	    reverse(Columns, LexColumns)
	),
	lex_chain(LexRows, [op(#<)/*,among(R,R,[1])*/]),
	lex_chain(LexColumns, [op(#=<)/*,among(K,K,[1])*/]),
	(   foreach(Row2,Rows),
	    param(R)
	do  sum(Row2, #=, R)
	),
	(   foreach(Col,Columns),
	    param(K)
	do  sum(Col, #=, K)
	),
	(   fromto(Rows,[Row0|Rest],Rest,[]),
	    param(Lambda)
	do  (   foreach(Row3,Rest),
		param([Row0,Lambda])
	    do  (   foreach(X,Row0),
		    foreach(Y,Row3),
		    foreach(Z,S)
		do  X #/\ Y #<=> Z
		),
		sum(S, #=, Lambda)
	    )
	).