/*-------------------------------------------------------------------------*/
/* Benchmark (Boolean)                                                     */
/*                                                                         */
/* Name           : bdiag.pl                                               */
/* Title          : N adder diagnostic                                     */
/* Original Source: Greg Sidebottom - University of Vancouver Canada       */
/* Adapted by     : Daniel Diaz for GNU Prolog                             */
/* Date           : September 1993                                         */
/*                                                                         */
/* The circuit diagnosis problem is as follows:                            */
/*                                                                         */
/*Given:                                                                   */
/*  1. a description of a digital circuit with a set of components C       */
/*  2. a function f computed by the circuit                                */
/*  3. a symptom consisting of an input output pair (i,o) such that        */
/*      f(i) <> o                                                          */
/* Find:                                                                   */
/*   a diagnosis D. D is a subset of C which, if not working correctly,    */
/*   could result in the circuit computing o given i.                      */
/*                                                                         */
/* The specific circuit used for this benchmark is an N bit adder with     */
/* forward carry propagation.  However, any combinatorial circuit diagnosis*/
/* problem could easily formulated from it's network description.          */
/* This example was constructed based on an example from an article about  */
/* Prolog III in CACM July 1990.                                           */
/* The problem consists in finding the minimum number of broken components */
/* in a N bit adder that thinks 0+0=2^N-1 (the answer is always N).        */
/* Each adder consists of 5 gates (2 'and', 2 'xor' and 1 'or').           */
/* A boolean (Di) is associated to each gate and it is true (1) if the     */
/* gate is broken. The solution is a list of Di. F is the number of broken */
/* components. To minimize F we label it (indomain) first (since there is  */
/* no choice point it is correct).                                         */
/*                                                                         */
/* Solution:                                                               */
/* N=1 [0,0,0,0,1]                                                         */
/* N=2 [0,0,0,0,1,0,0,0,0,1]                                               */
/* N=3 [0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]                                     */
/*-------------------------------------------------------------------------*/

q:-	statistics(runtime,_), write('N ?'), read_integer(N),
	Z is 1<<N-1,
	bdiag(N,0,0,Z,0,0,Ds,F), statistics(runtime,[_,Y]),
	write(s(F,Ds)), nl,
	write('time : '), write(Y), nl.




bdiag(N,X,Y,Z,C1,C,Ds,F):-
	N5 is N*5,
	F #=< N5,
	nadder(N,X,Y,Z,C1,C,Ds),
        TN is 1<<N,
	X+Y+C1 #\= Z+TN*C,
	sum(Ds,F),
	fd_minimize(fd_labeling(Ds),F).
%	fd_labeling([F|Ds]).




sum([],0).
sum([X|Xs],S):-
	S #= X + S1,
	sum(Xs,S1).




nadder(N,X,Y,Z,C1,C,Ds):-
	bits(N,X,Xs),
	bits(N,Y,Ys),
	bits(N,Z,Zs),
	adder(Xs,Ys,Zs,C1,C,Ds).




bits(N,X,Xs):-
	length(Xs,N),
	bits1(Xs,0,N,X).




bits1([],N,N,0).

bits1([Xi|Xs1],I,N,X):-
	I < N,
	X #= Xi * 2**I + X1,
	I1 is I + 1,
	bits1(Xs1,I1,N,X1).




adder([],[],[],C,C,[]).

adder([X|Xs],[Y|Ys],[Z|Zs],C1,C,[D0,D1,D2,D3,D4|Ds]):-
	fullAdder(X,Y,C1,Z,C2,D0,D1,D2,D3,D4),
	adder(Xs,Ys,Zs,C2,C,Ds).




fullAdder(X,Y,C1,Z,C,D0,D1,D2,D3,D4):-
	#\ D0 #==> (U1 #<=> X  #/\ Y),
	#\ D1 #==> (U2 #<=> U3 #/\ C1),
	#\ D2 #==> (C  #<=> U1 #\/ U2),
	#\ D3 #==> (U3 #<=> X  ## Y),
	#\ D4 #==> (Z  #<=> U3 ## C1).




:- initialization(q).

