blob: 66879532141b9a5f9ad27ebc31fc42d154ddfe6f [file] [log] [blame]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This is a rough approximation to the algorithm presented in:
%
% "An Algorithm for NAND Decomposition Under Network Constraints,"
% IEEE Trans. Comp., vol C-18, no. 12, Dec. 1969, p. 1098
% by E. S. Davidson.
%
% Written by Bruce Holmer
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% I have used the paper's terminology for names used in the program.
%
% The data structure for representing functions and variables is
% function(FunctionNumber, TrueSet, FalseSet,
% ConceivableInputs,
% ImmediatePredecessors, ImmediateSuccessors,
% Predecessors, Successors)
%
%
% Common names used in the program:
%
% NumVars number of variables (signal inputs)
% NumGs current number of variables and functions
% Gs list of variable and function data
% Gi,Gj,Gk,Gl individual variable or function--letter corresponds to
% the subscript in the paper (most of the time)
% Vector,V vector from a function's true set
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
main :- main(0).
main(N) :-
init_state(N, NumVars, NumGs, Gs),
add_necessary_functions(NumVars, NumGs, Gs, NumGs2, Gs2),
test_bounds(NumVars, NumGs2, Gs2),
search(NumVars, NumGs2, Gs2).
main(_) :-
write('Search completed'), nl.
% Test input
% init_state(circuit(NumInputs, NumOutputs, FunctionList))
init_state(0, 2, 3, [ % 2 input xor
function(2, [1,2], [0,3], [], [], [], [], []),
function(1, [2,3], [0,1], [], [], [], [], []),
function(0, [1,3], [0,2], [], [], [], [], [])
]) :-
update_bounds(_, 100, _).
init_state(1, 3, 4, [ % carry circuit
function(3, [3,5,6,7], [0,1,2,4], [], [], [], [], []),
function(2, [4,5,6,7], [0,1,2,3], [], [], [], [], []),
function(1, [2,3,6,7], [0,1,4,5], [], [], [], [], []),
function(0, [1,3,5,7], [0,2,4,6], [], [], [], [], [])
]) :-
update_bounds(_, 100, _).
init_state(2, 3, 4, [ % example in paper
function(3, [1,2,4,6,7], [0,3,5], [], [], [], [], []),
function(2, [4,5,6,7], [0,1,2,3], [], [], [], [], []),
function(1, [2,3,6,7], [0,1,4,5], [], [], [], [], []),
function(0, [1,3,5,7], [0,2,4,6], [], [], [], [], [])
]) :-
update_bounds(_, 100, _).
init_state(3, 3, 4, [ % sum (3 input xor)
function(3, [1,2,4,7], [0,3,5,6], [], [], [], [], []),
function(2, [4,5,6,7], [0,1,2,3], [], [], [], [], []),
function(1, [2,3,6,7], [0,1,4,5], [], [], [], [], []),
function(0, [1,3,5,7], [0,2,4,6], [], [], [], [], [])
]) :-
update_bounds(_, 100, _).
init_state(4, 3, 5, [ % do sum and carry together
function(4, [3,5,6,7], [0,1,2,4], [], [], [], [], []),
function(3, [1,2,4,7], [0,3,5,6], [], [], [], [], []),
function(2, [4,5,6,7], [0,1,2,3], [], [], [], [], []),
function(1, [2,3,6,7], [0,1,4,5], [], [], [], [], []),
function(0, [1,3,5,7], [0,2,4,6], [], [], [], [], [])
]) :-
update_bounds(_, 100, _).
init_state(5, 5, 8, [ % 2 bit full adder
function(7, % A2 (output)
[1,3,4,6,9,11,12,14,16,18,21,23,24,26,29,31],
[0,2,5,7,8,10,13,15,17,19,20,22,25,27,28,30],
[], [], [], [], []),
function(6, % B2 (output)
[2,3,5,6,8,9,12,15,17,18,20,21,24,27,30,31],
[0,1,4,7,10,11,13,14,16,19,22,23,25,26,28,29],
[], [], [], [], []),
function(5, % carry-out (output)
[7,10,11,13,14,15,19,22,23,25,26,27,28,29,30,31],
[0,1,2,3,4,5,6,8,9,12,16,17,18,20,21,24],
[], [], [], [], []),
function(4, % carry-in
[16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],
[], [], [], [], []),
function(3, % B1 input
[8,9,10,11,12,13,14,15,24,25,26,27,28,29,30,31],
[0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23],
[], [], [], [], []),
function(2, % B0 input
[4,5,6,7,12,13,14,15,20,21,22,23,28,29,30,31],
[0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27],
[], [], [], [], []),
function(1, % A1 input
[2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31],
[0,1,4,5,8,9,12,13,16,17,20,21,24,25,28,29],
[], [], [], [], []),
function(0, % A0 input
[1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31],
[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30],
[], [], [], [], [])
]) :-
update_bounds(_, 21, _).
% Iterate over all the TRUE vectors that need to be covered.
% If no vectors remain to be covered (select_vector fails), then
% the circuit is complete (printout results, update bounds, and
% continue search for a lower cost circuit).
search(NumVars, NumGsIn, GsIn) :-
select_vector(NumVars, NumGsIn, GsIn, Gj, Vector), !,
cover_vector(NumVars, NumGsIn, GsIn, Gj, Vector, NumGs, Gs),
add_necessary_functions(NumVars, NumGs, Gs, NumGsOut, GsOut),
test_bounds(NumVars, NumGsOut, GsOut),
search(NumVars, NumGsOut, GsOut).
search(NumVars, NumGs, Gs) :-
output_results(NumVars, NumGs, Gs),
update_bounds(NumVars, NumGs, Gs),
fail.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Given the current solution, pick the best uncovered TRUE vector
% for covering next.
% The selected vector is specified by its vector number and function.
% Select_vector fails if all TRUE vectors are covered.
% Select_vector is determinant (gives only one solution).
select_vector(NumVars, NumGs, Gs, Gj, Vector) :-
select_vector(Gs, NumVars, NumGs, Gs,
dummy, 0, nf, 999, Gj, Vector, Type, _), !,
\+ Type = cov,
\+ Type = nf.
% loop over functions
select_vector([Gk|_], NumVars, _, _, Gj, V, Type, N, Gj, V, Type, N) :-
function_number(Gk, K),
K < NumVars.
select_vector([Gk|Gks], NumVars, NumGs, Gs,
GjIn, Vin, TypeIn, Nin, GjOut, Vout, TypeOut, Nout) :-
function_number(Gk, K),
K >= NumVars,
true_set(Gk, Tk),
select_vector(Tk, Gk, NumVars, NumGs, Gs,
GjIn, Vin, TypeIn, Nin, Gj, V, Type, N),
select_vector(Gks, NumVars, NumGs, Gs,
Gj, V, Type, N, GjOut, Vout, TypeOut, Nout).
% loop over vectors
select_vector([], _, _, _, _, Gj, V, Type, N, Gj, V, Type, N).
select_vector([V|Vs], Gk, NumVars, NumGs, Gs,
GjIn, Vin, TypeIn, Nin, GjOut, Vout, TypeOut, Nout) :-
vector_cover_type(NumVars, Gs, Gk, V, Type, N),
best_vector(GjIn, Vin, TypeIn, Nin,
Gk, V, Type, N,
Gj2, V2, Type2, N2),
select_vector(Vs, Gk, NumVars, NumGs, Gs,
Gj2, V2, Type2, N2, GjOut, Vout, TypeOut, Nout).
vector_cover_type(NumVars, Gs, Gj, Vector, Type, NumCovers) :-
immediate_predecessors(Gj, IPs),
conceivable_inputs(Gj, CIs),
false_set(Gj, Fj),
cover_type1(IPs, Gs, Vector, nf, 0, T, N),
cover_type2(CIs, Gs, NumVars, Fj, Vector, T, N, Type, NumCovers).
cover_type1([], _, _, T, N, T, N).
cover_type1([I|IPs], Gs, V, TypeIn, Nin, TypeOut, Nout) :-
function(I, Gs, Gi),
true_set(Gi, Ti),
\+ set_member(V, Ti), !,
false_set(Gi, Fi),
(set_member(V, Fi) ->
max_type(TypeIn, cov, Type);
max_type(TypeIn, exp, Type)),
N is Nin + 1,
cover_type1(IPs, Gs, V, Type, N, TypeOut, Nout).
cover_type1([_|IPs], Gs, V, TypeIn, Nin, TypeOut, Nout) :-
cover_type1(IPs, Gs, V, TypeIn, Nin, TypeOut, Nout).
cover_type2([], _, _, _, _, T, N, T, N).
cover_type2([I|CIs], Gs, NumVars, Fj, V, TypeIn, Nin, TypeOut, Nout) :-
I < NumVars,
function(I, Gs, Gi),
false_set(Gi, Fi),
set_member(V, Fi), !,
max_type(TypeIn, var, Type),
N is Nin + 1,
cover_type2(CIs, Gs, NumVars, Fj, V, Type, N, TypeOut, Nout).
cover_type2([I|CIs], Gs, NumVars, Fj, V, TypeIn, Nin, TypeOut, Nout) :-
I >= NumVars,
function(I, Gs, Gi),
true_set(Gi, Ti),
\+ set_member(V, Ti), !,
false_set(Gi, Fi),
(set_member(V, Fi) ->
(set_subset(Fj, Ti) ->
max_type(TypeIn, fcn, Type);
max_type(TypeIn, mcf, Type));
(set_subset(Fj, Ti) ->
max_type(TypeIn, exf, Type);
max_type(TypeIn, exmcf, Type))),
N is Nin + 1,
cover_type2(CIs, Gs, NumVars, Fj, V, Type, N, TypeOut, Nout).
cover_type2([_|CIs], Gs, NumVars, Fj, V, TypeIn, Nin, TypeOut, Nout) :-
cover_type2(CIs, Gs, NumVars, Fj, V, TypeIn, Nin, TypeOut, Nout).
% The best vector to cover is the one with worst type, or, if types
% are equal, with the least number of possible covers.
best_vector(dummy, _, _, _, Gj2, V2, Type2, N2, Gj2, V2, Type2, N2) :- !.
best_vector(Gj1, V1, Type1, N1, dummy, _, _, _, Gj1, V1, Type1, N1) :- !.
best_vector(Gj1, V1, Type, N1, Gj2, _, Type, N2, Gj1, V1, Type, N1) :-
function_number(Gj1, J), function_number(Gj2, J),
N1 < N2, !.
best_vector(Gj1, _, Type, N1, Gj2, V2, Type, N2, Gj2, V2, Type, N2) :-
function_number(Gj1, J), function_number(Gj2, J),
N1 >= N2, !.
best_vector(Gj1, V1, Type, N1, Gj2, _, Type, _, Gj1, V1, Type, N1) :-
(Type = exp ; Type = var),
function_number(Gj1, J1), function_number(Gj2, J2),
J1 > J2, !.
best_vector(Gj1, _, Type, _, Gj2, V2, Type, N2, Gj2, V2, Type, N2) :-
(Type = exp ; Type = var),
function_number(Gj1, J1), function_number(Gj2, J2),
J1 < J2, !.
best_vector(Gj1, V1, Type, N1, Gj2, _, Type, _, Gj1, V1, Type, N1) :-
\+ (Type = exp ; Type = var),
function_number(Gj1, J1), function_number(Gj2, J2),
J1 < J2, !.
best_vector(Gj1, _, Type, _, Gj2, V2, Type, N2, Gj2, V2, Type, N2) :-
\+ (Type = exp ; Type = var),
function_number(Gj1, J1), function_number(Gj2, J2),
J1 > J2, !.
best_vector(Gj1, V1, Type1, N1, _, _, Type2, _, Gj1, V1, Type1, N1) :-
type_order(Type2, Type1), !.
best_vector(_, _, Type1, _, Gj2, V2, Type2, N2, Gj2, V2, Type2, N2) :-
type_order(Type1, Type2), !.
max_type(T1, T2, T1) :- type_order(T1, T2), !.
max_type(T1, T2, T2) :- \+ type_order(T1, T2), !.
% Order of types
type_order(cov, exp).
type_order(cov, var).
type_order(cov, fcn).
type_order(cov, mcf).
type_order(cov, exf).
type_order(cov, exmcf).
type_order(cov, nf).
type_order(exp, var).
type_order(exp, fcn).
type_order(exp, mcf).
type_order(exp, exf).
type_order(exp, exmcf).
type_order(exp, nf).
type_order(var, fcn).
type_order(var, mcf).
type_order(var, exf).
type_order(var, exmcf).
type_order(var, nf).
type_order(fcn, mcf).
type_order(fcn, exf).
type_order(fcn, exmcf).
type_order(fcn, nf).
type_order(mcf, exf).
type_order(mcf, exmcf).
type_order(mcf, nf).
type_order(exf, exmcf).
type_order(exf, nf).
type_order(exmcf, nf).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Cover_vector will cover the specified vector and
% generate new circuit information.
% Using backtracking, all possible coverings are generated.
% The ordering of the possible coverings is approximately that
% given in Davidson's paper, but has been simplified.
cover_vector(NumVars, NumGsIn, GsIn, Gj, Vector, NumGsOut, GsOut) :-
immediate_predecessors(Gj, IPs),
conceivable_inputs(Gj, CIs),
vector_types(Type),
cover_vector(Type, IPs, CIs, Gj, Vector, NumVars, NumGsIn, GsIn,
NumGsOut, GsOut).
vector_types(var).
vector_types(exp).
vector_types(fcn).
vector_types(mcf).
vector_types(exf).
vector_types(exmcf).
vector_types(nf).
cover_vector(exp, [I|_], _, Gj, V, _, NumGs, GsIn, NumGs, GsOut) :-
function(I, GsIn, Gi),
true_set(Gi, Ti),
\+ set_member(V, Ti),
update_circuit(GsIn, Gi, Gj, V, GsIn, GsOut).
cover_vector(exp, [_|IPs], _, Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
cover_vector(exp, IPs, _, Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut).
cover_vector(var, _, [I|_], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
I < NumVars,
function(I, GsIn, Gi),
false_set(Gi, Fi),
set_member(V, Fi),
update_circuit(GsIn, Gi, Gj, V, GsIn, GsOut).
cover_vector(var, _, [_|CIs], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
cover_vector(var, _, CIs, Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut).
cover_vector(fcn, _, [I|_], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
I >= NumVars,
function(I, GsIn, Gi),
false_set(Gi, Fi),
set_member(V, Fi),
true_set(Gi, Ti),
false_set(Gj, Fj),
set_subset(Fj, Ti),
update_circuit(GsIn, Gi, Gj, V, GsIn, GsOut).
cover_vector(fcn, _, [_|CIs], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
cover_vector(fcn, _, CIs, Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut).
cover_vector(mcf, _, [I|_], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
I >= NumVars,
function(I, GsIn, Gi),
false_set(Gi, Fi),
set_member(V, Fi),
true_set(Gi, Ti),
false_set(Gj, Fj),
\+ set_subset(Fj, Ti),
update_circuit(GsIn, Gi, Gj, V, GsIn, GsOut).
cover_vector(mcf, _, [_|CIs], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
cover_vector(mcf, _, CIs, Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut).
cover_vector(exf, _, [I|_], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
I >= NumVars,
function(I, GsIn, Gi),
false_set(Gi, Fi),
\+ set_member(V, Fi),
true_set(Gi, Ti),
\+ set_member(V, Ti),
false_set(Gj, Fj),
set_subset(Fj, Ti),
update_circuit(GsIn, Gi, Gj, V, GsIn, GsOut).
cover_vector(exf, _, [_|CIs], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
cover_vector(exf, _, CIs, Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut).
cover_vector(exmcf, _, [I|_], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
I >= NumVars,
function(I, GsIn, Gi),
false_set(Gi, Fi),
\+ set_member(V, Fi),
true_set(Gi, Ti),
\+ set_member(V, Ti),
false_set(Gj, Fj),
\+ set_subset(Fj, Ti),
update_circuit(GsIn, Gi, Gj, V, GsIn, GsOut).
cover_vector(exmcf, _, [_|CIs], Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut) :-
cover_vector(exmcf, _, CIs, Gj, V, NumVars, NumGs, GsIn, NumGs, GsOut).
cover_vector(nf, _, _, Gj, V, NumVars, NumGsIn, GsIn, NumGsOut, GsOut) :-
NumGsOut is NumGsIn + 1,
false_set(Gj, Fj),
new_function_CIs(GsIn,
function(NumGsIn,Fj,[V],[],[],[],[],[]),
NumVars, Gs, Gi),
update_circuit(Gs, Gi, Gj, V, Gs, GsOut).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
update_circuit([], _, _, _, _, []).
update_circuit([function(K,Tk,Fk,CIk,IPk,ISk,Pk,Sk)|GsIn],
Gi, Gj, V, Gs,
[function(K,Tko,Fko,CIko,IPko,ISko,Pko,Sko)|GsOut]) :-
Gi = function(I,_,Fi,_,IPi,ISi,Pi,_),
Gj = function(J,_,Fj,_,_,_,_,Sj),
set_union([I], Pi, PiI),
set_union([J], Sj, SjJ),
(K = J ->
set_union(Tk, Fi, Tk2);
Tk2 = Tk),
(K = I ->
set_union(Tk2, Fj, Tk3);
Tk3 = Tk2),
((set_member(K, IPi); set_member(K, ISi)) ->
set_union(Tk3, [V], Tko);
Tko = Tk3),
(K = I ->
set_union(Fk, [V], Fko);
Fko = Fk),
((set_member(K, Pi); K = I) ->
set_difference(CIk, SjJ, CIk2);
CIk2 = CIk),
((set_member(I, CIk), set_member(V, Fk)) ->
set_difference(CIk2, [I], CIk3);
CIk3 = CIk2),
(K = I ->
exclude_if_vector_in_false_set(CIk3, Gs, V, CIk4);
CIk4 = CIk3),
(K = J ->
set_difference(CIk4, [I], CIko);
CIko = CIk4),
(K = J ->
set_union(IPk, [I], IPko);
IPko = IPk),
(K = I ->
set_union(ISk, [J], ISko);
ISko = ISk),
(set_member(K, SjJ) ->
set_union(Pk, PiI, Pko);
Pko = Pk),
(set_member(K, PiI) ->
set_union(Sk, SjJ, Sko);
Sko = Sk),
update_circuit(GsIn, Gi, Gj, V, Gs, GsOut).
exclude_if_vector_in_false_set([], _, _, []).
exclude_if_vector_in_false_set([K|CIsIn], Gs, V, CIsOut) :-
function(K, Gs, Gk),
false_set(Gk, Fk),
set_member(V, Fk), !,
exclude_if_vector_in_false_set(CIsIn, Gs, V, CIsOut).
exclude_if_vector_in_false_set([K|CIsIn], Gs, V, [K|CIsOut]) :-
exclude_if_vector_in_false_set(CIsIn, Gs, V, CIsOut).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
add_necessary_functions(NumVars, NumGsIn, GsIn, NumGsOut, GsOut) :-
add_necessary_functions(NumVars, NumVars, NumGsIn, GsIn,
NumGsOut, GsOut).
add_necessary_functions(NumGs, _, NumGs, Gs, NumGs, Gs) :- !.
add_necessary_functions(K, NumVars, NumGsIn, GsIn, NumGsOut, GsOut) :-
function(K, GsIn, Gk),
function_type(NumVars, NumGsIn, GsIn, Gk, nf, V), !,
false_set(Gk, Fk),
new_function_CIs(GsIn,
function(NumGsIn,Fk,[V],[],[],[],[],[]),
NumVars, Gs, Gl),
function(K, Gs, Gk1),
update_circuit(Gs, Gl, Gk1, V, Gs, Gs1),
NumGs1 is NumGsIn + 1,
K1 is K + 1,
add_necessary_functions(K1, NumVars, NumGs1, Gs1, NumGsOut, GsOut).
add_necessary_functions(K, NumVars, NumGsIn, GsIn, NumGsOut, GsOut) :-
K1 is K + 1,
add_necessary_functions(K1, NumVars, NumGsIn, GsIn, NumGsOut, GsOut).
new_function_CIs(GsIn, function(L,Tl,Fl,_,IPl,ISl,Pl,Sl), NumVars,
[GlOut|GsOut], GlOut) :-
new_function_CIs(GsIn, L, Fl, NumVars, GsOut, [], CIlo),
GlOut = function(L,Tl,Fl,CIlo,IPl,ISl,Pl,Sl).
new_function_CIs([], _, _, _, [], CIl, CIl).
new_function_CIs([function(K,Tk,Fk,CIk,IPk,ISk,Pk,Sk)|GsIn], L, Fl, NumVars,
[function(K,Tk,Fk,CIko,IPk,ISk,Pk,Sk)|GsOut], CIlIn, CIlOut) :-
set_intersection(Fl, Fk, []), !,
(K >= NumVars ->
set_union(CIk, [L], CIko);
CIko = CIk),
new_function_CIs(GsIn, L, Fl, NumVars, GsOut, [K|CIlIn], CIlOut).
new_function_CIs([Gk|GsIn], L, Fl, NumVars, [Gk|GsOut], CIlIn, CIlOut) :-
new_function_CIs(GsIn, L, Fl, NumVars, GsOut, CIlIn, CIlOut).
function_type(NumVars, NumGs, Gs, Gk, Type, Vector) :-
true_set(Gk, Tk),
select_vector(Tk, Gk, NumVars, NumGs, Gs,
dummy, 0, nf, 999, _, Vector, Type, _).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Cost and constraint predicates:
% very simple bound for now
test_bounds(_, NumGs, _) :-
access(bound, Bound),
NumGs < Bound.
update_bounds(_, NumGs, _) :-
set(bound, NumGs).
% set and access for systems that don't support them
set(N, A) :-
(recorded(N, _, Ref) -> erase(Ref) ; true),
recorda(N, A, _).
access(N, A) :-
recorded(N, A, _).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Output predicates:
% for now just dump everything
output_results(NumVars, NumGs, Gs) :-
NumGates is NumGs - NumVars,
write(NumGates), write(' gates'), nl,
write_gates(Gs), nl,
write('searching for a better solution...'), nl, nl.
write_gates([]).
write_gates([Gi|Gs]) :-
function_number(Gi, I),
write('gate #'), write(I), write(' inputs: '),
immediate_predecessors(Gi, IPi),
write(IPi), nl,
write_gates(Gs).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Retrieve the specified function from the function list.
% function(FunctionNumber, FunctionList, Function).
function(I, [Gi|_], Gi) :- function_number(Gi, I), !.
function(I, [_|Gs], Gi) :- function(I, Gs, Gi).
function_number( function(I,_,_,_,_,_,_,_), I).
true_set( function(_,T,_,_,_,_,_,_), T).
false_set( function(_,_,F,_,_,_,_,_), F).
conceivable_inputs( function(_,_,_,CI,_,_,_,_), CI).
immediate_predecessors( function(_,_,_,_,IP,_,_,_), IP).
immediate_successors( function(_,_,_,_,_,IS,_,_), IS).
predecessors( function(_,_,_,_,_,_,P,_), P).
successors( function(_,_,_,_,_,_,_,S), S).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Set operations assume that the sets are represented by an ordered list
% of integers.
set_union([], [], []).
set_union([], [X|L2], [X|L2]).
set_union([X|L1], [], [X|L1]).
set_union([X|L1], [X|L2], [X|L3]) :- set_union(L1, L2, L3).
set_union([X|L1], [Y|L2], [X|L3]) :- X < Y, set_union(L1, [Y|L2], L3).
set_union([X|L1], [Y|L2], [Y|L3]) :- X > Y, set_union([X|L1], L2, L3).
set_intersection([], [], []).
set_intersection([], [_|_], []).
set_intersection([_|_], [], []).
set_intersection([X|L1], [X|L2], [X|L3]) :- set_intersection(L1, L2, L3).
set_intersection([X|L1], [Y|L2], L3) :- X < Y, set_intersection(L1, [Y|L2], L3).
set_intersection([X|L1], [Y|L2], L3) :- X > Y, set_intersection([X|L1], L2, L3).
set_difference([], [], []).
set_difference([], [_|_], []).
set_difference([X|L1], [], [X|L1]).
set_difference([X|L1], [X|L2], L3) :- set_difference(L1, L2, L3).
set_difference([X|L1], [Y|L2], [X|L3]) :- X < Y, set_difference(L1, [Y|L2], L3).
set_difference([X|L1], [Y|L2], L3) :- X > Y, set_difference([X|L1], L2, L3).
set_subset([], _).
set_subset([X|L1], [X|L2]) :- set_subset(L1, L2).
set_subset([X|L1], [Y|L2]) :- X > Y, set_subset([X|L1], L2).
set_member(X, [X|_]).
set_member(X, [Y|T]) :- X > Y, set_member(X, T).