% Machine representation is a list of transitions of the form 
% t(OldState, Input, Output, Direction, NewState)

:- data halts/1.
:- data loops/1.
:- data going/1. 
:- data blank/1. 
:- data grows/1. 
:- data hypes/1. 
:- data fragment/1. 
:- data fname/1. 
:- data ghalts/1.
:- data gloops/1.
:- data ggoing/1. 
:- data gblank/1. 
:- data ggrows/1. 
:- data ghypes/1. 
:- data records/1. 
:- data result/1. 
:- data writing/0.
:- data notwriting/0.

beaverbase("D:/busybeaver/Data/"). % Directory where results get written. 

ziptnf(_Machine,_Left, h, _Right, _Now, _History, _Bound, _Hops) :- !. 
ziptnf(_Machine, _Left, _State, _Right, _Now, _History, Bound, Hops) :- 
	Hops >= Bound, !. 
ziptnf(Machine, Left, State, [In|Right], Now, History, Bound, Hops) :-
	!, 
        member(t(State, In, Output, Dir, NewState), Machine), \+ member(state(Left, State, [In|Right]), History), 
	updateLR(Left, [In|Right], Output, Dir, NewLeft, NewRight), 
	NewHistory = [Now|History], 
	\+ escapecheck(NewLeft, NewState, NewRight, naive, Machine), 
	\+ blank(naive, NewLeft, NewRight), 
        Hops1 is Hops + 1, % format("Machine is ",[]), bbinternalprint(m,5,Machine,0,0,going), !, 
	ziptnf(Machine, NewLeft, NewState, NewRight, state(NewLeft, NewState, NewRight), NewHistory, Bound, Hops1). 

exploretnf(List, States, Symbols, [p(Final, In)], Left, State, Right, Now, History, Machine, Bound, Hops) :- 
       append(List, [t(Final, In, 1, r, h)], Machine), \+ ignore(States, Symbols, Machine), 
       ziptnf(Machine, Left, State, Right, Now, History, Bound, Hops).

exploretnf(List, States, Symbols,  Allocate, Left, State, [In|Right], Now, History, Machine, Bound, Hops) :-
        State \== h, Hops < Bound, length(Allocate, N), N > 1, 
        member(t(State, In, Output, Dir, NewState), List), \+ member(state(Left, State, [In|Right]), History), 
	updateLR(Left, [In|Right], Output, Dir, NewLeft, NewRight), 
	NewHistory = [Now|History], 
	\+ escapecheck(NewLeft, NewState, NewRight, naive, List), 
	\+ blank(naive, NewLeft, NewRight), 
        Hops1 is Hops + 1, 
	exploretnf(List, States, Symbols, Allocate, NewLeft, NewState, NewRight, state(NewLeft, NewState, NewRight), NewHistory, Machine, Bound, Hops1). 

exploretnf(List, States, Symbols, Allocate, Left, State, [In|Right], Now, History, Machine, Bound, Hops) :-
 	State \== h, Hops =< Bound, length(Allocate, N), N > 1, 
 	\+ member(t(State, In, _, _, _), List), 
        member(p(State, In), Allocate), 
	delete(Allocate, p(State, In), NewAllocate),  legitimate(List, NewState), 
 	member(Dir, [l,r]), 
	symbol(Symbols, Output), legal(List, Output), 
        append(List, [t(State, In, Output, Dir, NewState)], NewList),
        \+ ignore(States, Symbols, NewList), 
 	updateLR(Left, [In|Right], Output, Dir, NewLeft, NewRight), 
	NewHistory = [Now|History], 
	\+ escapecheck(NewLeft, NewState, NewRight, naive, List), 
	\+ blank(naive, NewLeft, NewRight), 
	Hops1 is Hops + 1, 
 	exploretnf(NewList, States, Symbols, NewAllocate, NewLeft, NewState, NewRight, state(NewLeft, NewState, NewRight), NewHistory, Machine, Bound, Hops1). 

symbol(2, 0). 
symbol(2, 1). 
symbol(3, 0). 
symbol(3, 1). 
symbol(3, 2). 
symbol(4, 0). 
symbol(4, 1). 
symbol(4, 2). 
symbol(4, 3). 
symbol(5, 0). 
symbol(5, 1). 
symbol(5, 2). 
symbol(5, 3). 
symbol(5, 4). 
symbol(6, 0). 
symbol(6, 1). 
symbol(6, 2). 
symbol(6, 3). 
symbol(6, 4). 
symbol(6, 5). 

legitimate(_, a).
legitimate(_, b).
legitimate(_, c).
legitimate(List, d) :- member(t(c,_,_,_,_), List). 
legitimate(List, e) :- member(t(c,_,_,_,_), List), member(t(d,_,_,_,_), List). 
legitimate(List, f) :- member(t(c,_,_,_,_), List), member(t(d,_,_,_,_), List), member(t(e,_,_,_,_), List). 

legal(_,0).
legal(_,1).
legal(_,2).
legal(List,3) :- member(t(_,_,2,_,_), List). 
legal(List,4) :- member(t(_,_,2,_,_), List), member(t(_,_,3,_,_), List). 
legal(List,5) :- member(t(_,_,2,_,_), List), member(t(_,_,3,_,_), List) , member(t(_,_,4,_,_), List). 

ignore(_, _,List) :- member(t(b,0,_,r,a), List), !. % loop case 1
ignore(_, _,List) :- member(t(b,0,_,r,b), List), !. % loop case 2
ignore(_, _,List) :- member(t(b,0,0,l,a), List), member(t(a,1,0,_,_), List), !. % case 3 fine for more symbols
ignore(_, _,List) :- member(t(b,0,0,l,a), List), member(t(a,1,1,r,a), List), !. % case 4 fine for more symbols
ignore(_, _,List) :- member(t(b,0,0,l,a), List), member(t(a,1,1,r,b), List), !. % case 4 fine for more symbols
ignore(_, _,List) :- member(t(b,0,0,l,a), List), member(t(a,1,1,l,b), List), !. % case 4 fine for more symbols
ignore(_, _,List) :- member(t(b,0,1,l,a), List), member(t(a,1,0,_,a), List), !. % case 5 fine for more symbols

ignore(_, _,List) :- member(t(b,0,0,l,b), List), member(t(b,1,0,_,_), List), !. % case 6 fine for more symbols
ignore(_, _,List) :- member(t(b,0,0,l,b), List), member(t(b,1,1,r,a), List), !. % fine fore more symbols
ignore(States, 2 ,List) :- States > 2, member(t(b,0,0,l,b), List), member(t(b,1,1,l,a), List), !. % two symbol case only

ignore(States, 2, List) :- States > 2, member(t(b,0,_,_,S3), List) , member(t(b,1,_,_,S4), List),
		member(t(a,1,_,_,S2), List), member(S2, [a,b]), member(S3, [a,b]), member(S4,[a,b]),!. 

ignore(_, _,List) :- member(t(b,0,1,l,a), List), member(t(a,1,1,l,c), List), member(t(b,1,0,l,c), List), member(t(c,0,0,l,a), List), !. % loop 21 fine for more symbols

ignore(_, _,List) :- member(t(b,0,0,l,a), List), member(t(a,1,1,l,a), List), member(t(b,1,0,l,c), List), member(t(c,1,0,l,d), List), !.  % fine for more symbols

ignore(States, Symbols, List) :- has_island(States, Symbols, List), !. 

has_island(_, Symbols, List) :- 
	member(t(S,_,_,_,_), List), complete([S], Symbols, List), all_transitions([S], List, States), all_in(States, [S]),
	true. 
has_island(Num, Symbols, List) :- 
	Num > 2, 
	member(t(S1,_,_,_,_), List), member(t(S2,_,_,_,_), List), 
	S1 \== S2, 
	complete([S1,S2], Symbols, List), 
	all_transitions([S1,S2], List, States), all_in(States, [S1,S2]), % 2-island
	true. 
has_island(Num, Symbols, List) :- 
	Num > 3, 
	member(t(S1,_,_,_,_), List), member(t(S2,_,_,_,_), List), member(t(S3,_,_,_,_), List), 
	S1 \== S2, S2 \== S3, S1 \== S3, 
	complete([S1,S2,S3], Symbols, List), 
	all_transitions([S1,S2,S3], List, States), all_in(States, [S1,S2,S3]), % 3-island
	true. 
has_island(Num, Symbols, List) :- 
	Num > 4, 
	member(t(S1,_,_,_,_), List), member(t(S2,_,_,_,_), List), member(t(S3,_,_,_,_), List), member(t(S4,_,_,_,_), List), 
	S1 \== S2, S2 \== S3, S1 \== S3, S1 \== S4, S2 \== S4, S3 \== S4, 
	complete([S1,S2,S3,S4], Symbols, List), 
        all_transitions([S1,S2,S3,S4], List, States), all_in(States, [S1,S2,S3,S4]), % 3-island
	true. 

all_transitions(S, M, States) :- findall(NewS, (member(S1, S),member(t(S1,_,_,_,NewS),M)), States). 

% Every element of List1 is in List2. This is tolerant of duplicates, so that all_in([1,2,1,1], [2,1]) succeeds. 
all_in([], _). 
all_in([Element|Rest], List) :-
	member(Element, List),
	all_in(Rest, List). 

% complete(States, Symbols, List)
% Each State has a transition in List for each symbol in Symbols.

complete([], _, _).
complete([S|States], Symbols, List) :-
	total(S, Symbols, List),
	complete(States, Symbols, List).

total(_S, [], _).
total(S, [Sym1|Rest], List) :-
	member(t(S,Sym1,_,_,_), List),
	total(S, Rest, List).


has_island2(_Symbols, List) :- member(t(S,0,_,_,S), List), member(t(S,1,_,_,S), List), !. 
has_island2(_Symbols, List) :- member(t(S1,0,_,_,N1), List), member(t(S1,1,_,_,N2), List), % 2-island 
	            member(t(S2,0,_,_,N3), List), member(t(S2,1,_,_,N4), List),
		    S1 \== S2, 
		    member(N1, [S1,S2]), % this means h cannot be N1,N2,N3,N4
		    member(N2, [S1,S2]),
		    member(N3, [S1,S2]),
		    member(N4, [S1,S2]),!.

has_island2(_Symbols, List) :- member(t(S1,0,_,_,N1), List), member(t(S1,1,_,_,N2), List), % 3-island
	            member(t(S2,0,_,_,N3), List), member(t(S2,1,_,_,N4), List),
	            member(t(S3,0,_,_,N5), List), member(t(S3,1,_,_,N6), List),
		    S1 \== S2, S2 \== S3, S1 \== S3, 
		    member(N1, [S1,S2,S3]), % this means h cannot be N1,N2,N3,N4,N5,N6
		    member(N2, [S1,S2,S3]),
		    member(N3, [S1,S2,S3]),
		    member(N4, [S1,S2,S3]),
		    member(N5, [S1,S2,S3]),
		    member(N6, [S1,S2,S3]),!.
		    
has_island2(_Symbols, List) :- member(t(S1,0,_,_,N1), List), member(t(S1,1,_,_,N2), List), % 4-island
	            member(t(S2,0,_,_,N3), List), member(t(S2,1,_,_,N4), List),
	            member(t(S3,0,_,_,N5), List), member(t(S3,1,_,_,N6), List),
	            member(t(S4,0,_,_,N7), List), member(t(S4,1,_,_,N8), List),
		    S1 \== S2, S2 \== S3, S1 \== S3, S1 \== S4, S2 \== S4, S3 \== S4, 
		    member(N1, [S1,S2,S3,S4]), % this means h cannot be N1,N2,N3,N4,N5,N6,N7,N8
		    member(N2, [S1,S2,S3,S4]),
		    member(N3, [S1,S2,S3,S4]),
		    member(N4, [S1,S2,S3,S4]),
		    member(N5, [S1,S2,S3,S4]),
		    member(N6, [S1,S2,S3,S4]),
		    member(N7, [S1,S2,S3,S4]),
		    member(N8, [S1,S2,S3,S4]),!.
		    
% has_circuit(States, Symbols, List) :- 
% 	             member(t(S1, I1, _O1, D1, S2), List), 
%                      member(t(S2, 0, I1, D2, S1), List), member(t(S2, 1, I1, D2, S1), List),
% 	             S1 \== S2, opposite(D1,D2).
% 
% has_circuit2(Symbols, List) :- member(t(S1, I1, _O1, D1, S2), List), 
%                      member(t(S2, 0, I1, D2, S1), List), member(t(S2, 1, I1, D2, S1), List),
% 	             S1 \== S2, opposite(D1,D2).

opposite(l,r).
opposite(r,l).

filelinemax(500000) :- !. % maximum number of lines to write to a file before starting a new one. 

%% A very hacky way to write out the generated machines from within a failure=driven loop. There must be a better way ... 
breakout(N, M, Ones, Hops, Status) :-
	notwriting, !, 
	fragment(Frag),
	fname(Base), number_codes(Frag, Name),
	append(Base, Name, F1),	append(F1, ".pl", F), 
	string2term(F, File),
	retractall(halts(_)), retractall(loops(_)), retractall(going(_)), retractall(blank(_)), retractall(grows(_)), retractall(hypes(_)), 
	assert(halts(0)), assert(loops(0)), assert(going(0)), assert(blank(0)), assert(grows(0)), assert(hypes(0)), 
	tell(File),
	bbinternalprint(bb, N, M, Ones, Hops, Status),
	updatestats(Status), 
	retractall(notwriting), assert(writing), !.

breakout(N, M, Ones, Hops, Status) :-
	writing, current_output(Stream), line_count(Stream, Count), 
 	filelinemax(Max), Count > 0, Count < Max, !, % Keep writing to same file
	bbinternalprint(bb, N, M, Ones, Hops, Status),
	updatestats(Status), !. 

breakout(N, M, Ones, Hops, Status) :-
	writing, current_output(Stream), line_count(Stream, Count), 
 	filelinemax(Max), Count >= Max, !, % Time for a new file 
	retract(fragment(Frag)),
	Frag1 is Frag + 1,
	assert(fragment(Frag1)), 
	fname(Base), number_codes(Frag1, Name),
	append(Base, Name, F1), append(F1, ".pl", F), 
	string2term(F, File),
	retract(halts(Halts)), 	retract(loops(Loops)), retract(going(Going)), retract(blank(Blank)), retract(grows(Grow)), retract(hypes(Hyp)), 
 	assert(halts(0)), assert(loops(0)), assert(going(0)), assert(blank(0)), assert(grows(0)), assert(hypes(0)),  
	format("% Halt: ~d Loop: ~d Grow: ~d Blank: ~d Going: ~d Hyp: ~d~n", [Halts, Loops, Grow, Blank, Going, Hyp]), 
        pivot(small,MaxPS), pivot(large,MaxPL), nonpivot(small,MaxNS), nonpivot(large, MaxNL), hypmax(small,HMaxS), hypmax(HMaxL), smallhist(MaxHS), largehist(MaxHL), 
        format("% Parameters are pivot: ~d and ~d, nonpivot: ~d and ~d hypmax: ~d and ~d, maxhist ~d and ~d~n", [MaxPS, MaxPL, MaxNS, MaxNL, HMaxS, HMaxL, MaxHS, MaxHL]), 
	retract(ghalts(GH)), retract(gloops(GL)), retract(ggoing(GO)), retract(gblank(GB)), retract(ggrows(GG)), retract(ghypes(GHyp)), 
	GH1 is GH + Halts, GL1 is GL + Loops, GO1 is GO + Going, GB1 is GB + Blank, GG1 is GG + Grow, GHyp1 is GHyp + Hyp,  
	assert(ghalts(GH1)), assert(gloops(GL1)), assert(ggoing(GO1)), assert(gblank(GB1)), assert(ggrows(GG1)),  assert(ghypes(GHyp1)),    
	records(R), printlist(R), 
	told, !, 
	tell(File),
	bbinternalprint(bb, N, M, Ones, Hops, Status),
	updatestats(Status), !. 

bbinternalprint(Pred, N, M, O, H, Status) :-
	format("~k(~d,[", [Pred,N]),!, 
	printint(M), !, 
	format("],~d,~d,", [O,H]),!, 
	display(Status), !,  
	format(").~n", []), !. 

printlist([]) :- !.
printlist([max(O, M, H)|Rest]) :- 
	!, format("% ", []), bbinternalprint(maximum, 5, M, O, H, halts),
	printlist(Rest).
printlist([min(O, M, H)|Rest]) :- 
	!, format("% ", []), bbinternalprint(minimum, 5, M, O, H, halts),
	printlist(Rest).

printint([]) :- !. 
printint([A]) :- format("~k", [A]), !. 
printint(Arg) :- Arg = [A1|Temp], Temp = [A2|Rest], !, format("~k,", [A1]), !, printint([A2|Rest]).

bbsortout(Pred, N, M) :-
	format("~k(~d, [", [Pred,N]),
	sortmachine(N, 1, 0, [], M, M1), !, 
	printint(M1),
	format("]).~n", []).

sortmachine(_N, _State, _Input, Done, [], M) :- reverse(Done, M),!. 
sortmachine(N, State, Input, Done, Todo, Result) :-
	length(Todo, T), T > 0,
	member(t(State, Input, Output, Dir, NewState), Todo), !, 
	delete(Todo, t(State, Input, Output, Dir, NewState), Rest),
	increment(State, Input, NS, NI), !, 
	sortmachine(N, NS, NI, [t(State, Input, Output, Dir, NewState)|Done], Rest, Result).

sortmachine(N, State, Input, Done, Todo, Result) :-
	length(Todo, T), T > 0,
	\+ member(t(State, Input, _Output, _Dir, _NewState), Todo), !, 
	increment(State, Input, NS, NI), !,
	sortmachine(N, NS, NI, Done, Todo, Result).

increment(S, 0, S, 1).
increment(a,1,b,0).
increment(b,1,c,0).
increment(c,1,d,0).
increment(d,1,e,0).
increment(e,1,f,0).
increment(f,1,g,0).

updatestats(halts):- !, retract(halts(Halts)), H is Halts + 1, assert(halts(H)),!. 
updatestats(meander):- !, retract(loops(Loops)), L is Loops + 1, assert(loops(L)),!. 
updatestats(loops(cycle(_))):- !, retract(loops(Loops)), L is Loops + 1, assert(loops(L)),!. 
updatestats(loops(cycle)):- !, retract(loops(Loops)), L is Loops + 1, assert(loops(L)),!. 
updatestats(loops):- !, retract(loops(Loops)), L is Loops + 1, assert(loops(L)),!. 
updatestats(loops(induction(_,_,_,_))):- !, retract(loops(Loops)), L is Loops + 1, assert(loops(L)),!. 
updatestats(loops(induction(_,_))):- !, retract(loops(Loops)), L is Loops + 1, assert(loops(L)),!. 
updatestats(loops(dizzyduck(_))):- !, retract(grows(Grows)), G is Grows + 1, assert(grows(G)),!. 
updatestats(loops(growing(_))):- !, retract(grows(Grows)), G is Grows + 1, assert(grows(G)),!. 
updatestats(blank):- !, retract(blank(Blank)), B is Blank + 1, assert(blank(B)),!. 
updatestats(halts(_)):- !, retract(hypes(Hypes)), H is Hypes + 1, assert(hypes(H)),!. 
updatestats(hyp(_)):- !, retract(hypes(Hypes)), H is Hypes + 1, assert(hypes(H)),!. 
updatestats(going):- !, retract(going(Going)), G is Going + 1, assert(going(G)),!. 

search(States, Symbols) :- search(States, Symbols, restricted).
search(1, _Symbols, _Mode) :-
	beaverbase(B), append(B, "busybeaver1.pl", F), string2term(F, File), 
	tell(File),
	find(1,_, _,_),
	told. 

search(States, Symbols, Mode) :-
	States >= 2, States =< 4, Symbols >= 2, Symbols =< 4, States*Symbols =< 8, % Small cases will fit in one file
	
	retractall(halts(_)), retractall(loops(_)), retractall(going(_)), retractall(blank(_)), retractall(grows(_)), retractall(hypes(_)), 
	retractall(records(_)), 

	assert(halts(0)), assert(loops(0)), assert(going(0)), assert(blank(0)), assert(grows(0)), assert(hypes(0)), 	
	assert(records([])),  
	number_codes(States, S1), number_codes(Symbols, S2), modecode(Mode, Extra), 
	beaverbase(B), append("busybeaver", S1, S2, TName), append(TName, Extra, ".pl", Name), append(B, Name, F), string2term(F, File), 
	append(TName, Extra, "-going.pl", Name2), append(B, Name2, F2), string2term(F2, GoingFile), 
	tell(File), 
	open(GoingFile, write, GoFile), 
	find(States, Symbols, Mode, GoFile), 

	retract(halts(Halts)),	retract(loops(Loops)), retract(going(Going)), retract(blank(Blank)), retract(grows(Grow)), retract(hypes(Hypes)), 
	format("% Overall statistics are Halt: ~d Loop: ~d Grow: ~d Blank: ~d Going: ~d Hypotheses: ~d~n", [Halts, Loops, Grow, Blank, Going, Hypes]), 
        pivot(small,MaxPS), pivot(large,MaxPL), nonpivot(small,MaxNS), nonpivot(large, MaxNL), hypmax(small,HMaxS), hypmax(large,HMaxL), smallhist(MaxHS), largehist(MaxHL), 
        format("% Parameters are pivot: ~d and ~d, nonpivot: ~d and ~d hypmax: ~d and ~d, maxhist ~d and ~d~n", [MaxPS, MaxPL, MaxNS, MaxNL, HMaxS, HMaxL, MaxHS, MaxHL]), 
	retract(records(R)), printlist(R), 
	told.

search(States, Symbols, free) :-
	(States >= 5; Symbols >= 3), States =< 5, Symbols =< 5, States * Symbols =< 10, % larger cases, but not too large -- 2x5, 3x3, 5x2 only
	 format("Sorry, this is too large for a free search~n", []). 
search(States, Symbols, restricted) :-
	(States >= 5; Symbols >= 3), States =< 5, Symbols =< 5, States * Symbols =< 10, % larger cases, but not too large -- 2x5, 3x3, 5x2 only
	 % Need to break output up into a number of files in these cases. 
	format("Opening file~n", []), 

	number_codes(States, S1), number_codes(Symbols, S2), 
	beaverbase(B), append("busybeaver", S1, S2, TName), 
	append(TName, "-going.pl", Name2), append(B, Name2, F), string2term(F, GoingFile), 

	open(GoingFile, write, GoFile), 

	retractall(halts(_)), retractall(loops(_)), retractall(going(_)), retractall(blank(_)), retractall(grows(_)), retractall(hypes(_)), 
	retractall(ghalts(_)), retractall(gloops(_)), retractall(ggoing(_)), retractall(gblank(_)), retractall(ggrows(_)), retractall(ghypes(_)), 
	retractall(records(_)), 

	assert(ghalts(0)), assert(gloops(0)), assert(ggoing(0)), assert(gblank(0)), assert(ggrows(0)), assert(ghypes(0)), 
	assert(records([])),  
	format("Searching ~n", []), 
	search_machines(States, Symbols, GoFile), 

	retract(ghalts(Halts)),	retract(gloops(Loops)), retract(ggoing(Going)), retract(gblank(Blank)), retract(ggrows(Grow)), retract(ghypes(Hypes)),   
	format("% Overall statistics are Halt: ~d Loop: ~d Grow: ~d Blank: ~d Going: ~d Hyp: ~d ~n", [Halts, Loops, Grow, Blank, Going, Hypes]), 
        pivot(small,MaxPS), pivot(large,MaxPL), nonpivot(small,MaxNS), nonpivot(large, MaxNL), hypmax(small,HMaxS), hypmax(large,HMaxL), smallhist(MaxHS), largehist(MaxHL), 
        format("% Parameters are pivot: ~d and ~d, nonpivot: ~d and ~d hypmax: ~d and ~d, maxhist ~d and ~d~n", [MaxPS, MaxPL, MaxNS, MaxNL, HMaxS, HMaxL, MaxHS, MaxHL]), 
	retract(records(R)), printlist(R), 
	close(GoFile), 
	true. 

search(States, Symbols, _Mode) :-
	(States >= 6; Symbols >= 6; States * Symbols > 10), format("Too big! Sorry!~n", []). 

modecode(free, "free").
modecode(restricted, []).

% freesearch(States, Symbols, GoFile) :-

find(1, _, _, _) :- 
	bbinternalprint(bb, 1, [t(a,0,1,r,h)], 1, 1, halts).

find(States, Symbols, restricted, GoFile) :- States >= 2, States =< 4,  
	tnf(States, Symbols, M), 
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
        test(GoFile, States, M, Ones, Hops, Status), 
        bbinternalprint(bb, States, M, Ones, Hops, Status),
	fail.
find(_,_,restricted, _) :- !. 

find(States, Symbols, free, _) :- States >= 2, States =< 4,  
	Symbols >= 2, Symbols =< 4, States * Symbols =< 8, % Dont' allow 4x4 for example ...
	free(States, Symbols).

free(2,2) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,O2,D2,S2),t(b,1,1,r,h)],
	member(O1, [0,1]), member(O2, [0,1]), 
	member(S1, [a,b]), member(S2, [a,b]), 
	member(D2, [l,r]), 
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
 	bbinternalprint(bb, 2, M, Ones, Hops, Status),
	n2to2n(M, DualM), 
	analyse(DualM, DOnes, DHops, DStatus), 
 	bbinternalprint(d2, 2, DualM, DOnes, DHops, DStatus),
	fail.
free(2,2) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,1,r,h),t(b,1,O3,D3,S3)],
	member(O1, [0,1]), member(O3, [0,1]), 
	member(S1, [a,b]), member(S3, [a,b]), 
	member(D3, [l,r]), 
        analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
 	bbinternalprint(bb, 2, M, Ones, Hops, Status),
	n2to2n(M, DualM), 
	analyse(DualM, DOnes, DHops, DStatus), 
 	bbinternalprint(d2, 2, DualM, DOnes, DHops, DStatus),
	fail.
free(2,2). 

free(2,3) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,O2,D2,S2),t(b,1,1,r,h),t(a,2,O3,D3,S3),t(b,2,O4,D4,S4)],
	member(O1, [0,1,2]), member(O2, [0,1,2]), member(O3, [0,1,2]), member(O4,[0,1,2]), 
	member(S1, [a,b]), member(S2, [a,b]), member(S3, [a,b]), member(S4,[a,b]), 
	member(D2, [l,r]), member(D3, [l,r]), member(D4, [l,r]), 
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
	stats(M, Ones, Hops, Status), 
	bbinternalprint(bb, 2, M, Ones, Hops, Status), 
	fail. 
free(2,3) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,1,r,h),t(b,1,O2,D2,S2),t(a,2,O3,D3,S3),t(b,2,O4,D4,S4)],
	member(O1, [0,1,2]), member(O2, [0,1,2]), member(O3, [0,1,2]), member(O4,[0,1,2]), 
	member(S1, [a,b]), member(S2, [a,b]), member(S3, [a,b]), member(S4,[a,b]), 
	member(D2, [l,r]), member(D3, [l,r]), member(D4, [l,r]), 
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
	stats(M, Ones, Hops, Status), 
	bbinternalprint(bb, 2, M, Ones, Hops, Status), 
	fail. 
free(2,3) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,O2,D2,S2),t(b,1,O3,D3,S3),t(a,2,1,r,h),t(b,2,O4,D4,S4)],
	member(O1, [0,1,2]), member(O2, [0,1,2]), member(O3, [0,1,2]), member(O4,[0,1,2]), 
	member(S1, [a,b]), member(S2, [a,b]), member(S3, [a,b]), member(S4,[a,b]), 
	member(D2, [l,r]), member(D3, [l,r]), member(D4, [l,r]), 
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
	stats(M, Ones, Hops, Status), 
	bbinternalprint(bb, 2, M, Ones, Hops, Status), 
	fail. 

free(2,3) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,O2,D2,S2),t(b,1,O3,D3,S3),t(a,2,O4,D4,S4),t(b,2,1,r,h)],
	member(O1, [0,1,2]), member(O2, [0,1,2]), member(O3, [0,1,2]), member(O4,[0,1,2]), 
	member(S1, [a,b]), member(S2, [a,b]), member(S3, [a,b]), member(S4,[a,b]), 
	member(D2, [l,r]), member(D3, [l,r]), member(D4, [l,r]), 
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
	stats(M, Ones, Hops, Status), 
	bbinternalprint(bb, 2, M, Ones, Hops, Status), 
	fail. 
free(2,3).

free(3,2) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,O2,D2,S2),t(b,1,O3,D3,S3),t(c,0,O4,D4,S4),t(c,1,1,r,h)], 
	member(O1, [0,1]), member(O2, [0,1]), member(O3, [0,1]), member(O4, [0,1]), 
	member(S1, [a,b,c]), member(S2, [a,b,c]), member(S3, [a,b,c]), member(S4, [a,b,c]), 
	member(D2, [l,r]), member(D3, [l,r]), member(D4, [l,r]),  
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
	stats(M, Ones, Hops, Status), 
 	bbinternalprint(bb, 3, M, Ones, Hops, Status),
	fail.
free(3,2) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,O2,D2,S2),t(b,1,O3,D3,S3),t(c,0,1,r,h),t(c,1,O5,D5,S5)],
	member(O1, [0,1]), member(O2, [0,1]), member(O3, [0,1]), member(O5, [0,1]), 
	member(S1, [a,b,c]), member(S2, [a,b,c]), member(S3, [a,b,c]), member(S5, [a,b,c]), 
	member(D2, [l,r]), member(D3, [l,r]), member(D5, [l,r]),  
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
	stats(M, Ones, Hops, Status), 
 	bbinternalprint(bb, 3, M, Ones, Hops, Status),
	fail.
free(3,2) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,O2,D2,S2),t(b,1,1,r,h),t(c,0,O4,D4,S4),t(c,1,O5,D5,S5)],
	member(O1, [0,1]), member(O2, [0,1]), member(O4, [0,1]), member(O5, [0,1]), 
	member(S1, [a,b,c]), member(S2, [a,b,c]), member(S4, [a,b,c]), member(S5, [a,b,c]), 
	member(D2, [l,r]), member(D4, [l,r]), member(D5, [l,r]),  
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
	stats(M, Ones, Hops, Status), 
 	bbinternalprint(bb, 3, M, Ones, Hops, Status),
	fail.
free(3,2) :-
	M = [t(a,0,1,r,b),t(b,0,O1,l,S1),t(a,1,1,r,h),t(b,1,O3,D3,S3),t(c,0,O4,D4,S4),t(c,1,O5,D5,S5)],
	member(O1, [0,1]), member(O3, [0,1]), member(O4, [0,1]), member(O5, [0,1]), 
	member(S1, [a,b,c]), member(S3, [a,b,c]), member(S4, [a,b,c]), member(S5, [a,b,c]), 
	member(D3, [l,r]), member(D4, [l,r]), member(D5, [l,r]),  
	analyse(M, Ones, Hops, Status), 
	updatestats(Status), 
	stats(M, Ones, Hops, Status), 
 	bbinternalprint(bb, 3, M, Ones, Hops, Status),
	fail.
free(3,2). 
% Should add code for other cases here

search_machines(States, Symbols, GoFile) :-
	retractall(fname(_)), retractall(writing), retractall(notwriting), retractall(fragment(_)), 
	number_codes(States, S1), number_codes(Symbols, S2), 
	beaverbase(B), append("busybeaver", S1, S2, Name), append(B, Name, F), 
	assert(fname(F)), format("~s~n", [F]), 
	assert(notwriting), assert(fragment(1)),  
  	tnf(States, Symbols, M), 
	analyse(M, Ones, Hops, Status), 
        test(GoFile, States, M, Ones, Hops, Status), 
	breakout(States, M, Ones, Hops, Status), 
	fail.
search_machines(_, _, _) :-  
	% exhausted tnf, so finish up ... 
	retract(halts(Halts)), 	retract(loops(Loops)), retract(going(Going)), retract(blank(Blank)), retract(grows(Grow)), retract(hypes(Hyp)), 
	format("% Halt: ~d Loop: ~d Grow: ~d Blank: ~d Going: ~d HypL ~d~n", [Halts, Loops, Grow, Blank, Going, Hyp]), 
	retract(ghalts(GH)), retract(gloops(GL)), retract(ggoing(GO)), retract(gblank(GB)), retract(ggrows(GG)),   retract(ghypes(GHyp)),   
	GH1 is GH + Halts, GL1 is GL + Loops, GO1 is GO + Going, GB1 is GB + Blank, GG1 is GG + Grow, GHyp1 is GHyp + Hyp, 
	assert(ghalts(GH1)), assert(gloops(GL1)), assert(ggoing(GO1)), assert(gblank(GB1)), assert(ggrows(GG1)),   assert(ghypes(GHyp1)),   
	format("% Overall statistics are Halt: ~d Loop: ~d Grow: ~d Blank: ~d Going: ~d Hyp: ~d ~n", [GH1, GL1, GG1, GB1, GO1,GHyp1]), 
        pivot(small,MaxPS), pivot(large,MaxPL), nonpivot(small,MaxNS), nonpivot(large, MaxNL), hypmax(small,HMaxS), hypmax(large,HMaxL), smallhist(MaxHS), largehist(MaxHL), 
        format("% Parameters are pivot: ~d and ~d, nonpivot: ~d and ~d hypmax: ~d and ~d, maxhist ~d and ~d~n", [MaxPS, MaxPL, MaxNS, MaxNL, HMaxS, HMaxL, MaxHS, MaxHL]), 
	records(R), printlist(R), !.
	
tnf(States, Symbols, []) :-
	\+ (States >=1, States =< 5, Symbols >= 2, Symbols =< 5), format("Out of range~n", []). 

tnf(1, _, [t(a,0,1,r,h), t(a,1,1,r,a)]). 
tnf(2, 2, Machine) :-
	start(2, _, T), \+ member(t(_,_,_,_,c), T), 
	exploretnf(T, 2, 2, [p(a,1),p(b,1)], [], a, [0], state([], a, [0]), [], Machine, 100, 0),
	true. 
tnf(2, 3, Machine) :-
	start(3, _, T), \+ member(t(_,_,_,_,c), T), 
	exploretnf(T, 2, 3, [p(a,1),p(a,2),p(b,1),p(b,2)], [], a, [0], state([], a, [0]), [], Machine, 100, 0),
	true. 

tnf(2, 4, Machine) :-
	start(4, _, T), \+ member(t(_,_,_,_,c), T), 
	exploretnf(T, 2, 4, [p(a,1),p(a,2),p(a,3),p(b,1),p(b,2),p(b,3)], [], a, [0], state([], a, [0]), [], Machine, 100, 0),
	true. 

tnf(2, 5, Machine) :-
	start(5, _, T), \+ member(t(_,_,_,_,c), T), 
	exploretnf(T, 2, 5, [p(a,1),p(a,2),p(a,3),p(a,4),p(b,1),p(b,2),p(b,3),p(b,4)], [], a, [0], state([], a, [0]), [], Machine, 100, 0),
	\+ redundant(Machine), 
	\+ ignore(2, 5, Machine), 
	true. 

tnf(3, 2, Machine) :-
	start(2, _, T), 
	exploretnf(T, 3, 2, [p(a,1),p(b,1),p(c,0),p(c,1)], [], a, [0], state([], a, [0]), [], Machine, 100, 0),
	true. 

tnf(4, 2, Machine) :-
	start(2, _, T),
	exploretnf(T, 4, 2, [p(a,1),p(b,1),p(c,0),p(c,1),p(d,0),p(d,1)], [], a, [0], state([], a, [0]), [], Machine, 100, 0),
	length(Machine, 8),
 	\+ redundant(Machine),
	\+ ignore(5, 2, Machine). 

tnf(3, 3, Machine) :-
	start(3, _, T), 
	exploretnf(T, 3, 2, [p(a,1),p(a,2),p(b,1),p(b,2),p(c,0),p(c,1),p(c,2)], [], a, [0], state([], a, [0]), [], Machine, 100, 0),
	true. 

tnf(5, 2, Machine) :- tnf(5,2,1,Machine).
tnf(5, 2, Machine) :- tnf(5,2,2,Machine).
tnf(5, 2, Machine) :- tnf(5,2,3,Machine).
tnf(5, 2, Machine) :- tnf(5,2,4,Machine).
tnf(5, 2, Machine) :- tnf(5,2,5,Machine).
tnf(5, 2, Machine) :- tnf(5,2,6,Machine).
tnf(5, 2, Machine) :- tnf(5,2,7,Machine).
tnf(5, 2, Machine) :- tnf(5,2,8,Machine).

tnf(5, 2, Num, Machine) :-
	start(2, Num, T), 
 	exploretnf(T, 5, 2, [p(a,1),p(b,1),p(c,0),p(c,1),p(d,0),p(d,1),p(e,0),p(e,1)], [], a, [0], 
                                                  state([], a, [0]), [], Machine, 100, 0),
	\+ redundant(Machine),
	\+ ignore(5, 2, Machine).

start(2, 1, [t(a,0,1,r,b), t(b,0,0,l,a)]). 
start(2, 2, [t(a,0,1,r,b), t(b,0,1,l,a)]). 
start(2, 3, [t(a,0,1,r,b), t(b,0,0,l,b)]). 
start(2, 4, [t(a,0,1,r,b), t(b,0,1,l,b)]). 
start(2, 5, [t(a,0,1,r,b), t(b,0,0,r,c)]). 
start(2, 6, [t(a,0,1,r,b), t(b,0,1,r,c)]). 
start(2, 7, [t(a,0,1,r,b), t(b,0,0,l,c)]). 
start(2, 8, [t(a,0,1,r,b), t(b,0,1,l,c)]). 
start(N, Num, T) :- 	N > 2, startn(Num, T). 

startn(1,  [t(a,0,1,r,b), t(b,0,0,l,a)]). 
startn(2,  [t(a,0,1,r,b), t(b,0,1,l,a)]). 
startn(3,  [t(a,0,1,r,b), t(b,0,2,l,a)]). 
startn(4,  [t(a,0,1,r,b), t(b,0,0,l,b)]). 
startn(5,  [t(a,0,1,r,b), t(b,0,1,l,b)]). 
startn(6,  [t(a,0,1,r,b), t(b,0,2,l,b)]). 
startn(7,  [t(a,0,1,r,b), t(b,0,0,r,c)]). 
startn(8,  [t(a,0,1,r,b), t(b,0,1,r,c)]). 
startn(9,  [t(a,0,1,r,b), t(b,0,2,r,c)]). 
startn(10, [t(a,0,1,r,b), t(b,0,0,l,c)]). 
startn(11, [t(a,0,1,r,b), t(b,0,1,l,c)]). 
startn(12, [t(a,0,1,r,b), t(b,0,2,l,c)]). 

start2(Symbols, [t(a,0,1,r,b), t(b,0,Output,l,a)]) :-	symbol(Symbols, Output). 
start2(Symbols, [t(a,0,1,r,b), t(b,0,Output,l,b)]) :-	symbol(Symbols, Output).  
start2(Symbols, [t(a,0,1,r,b), t(b,0,Output,r,c)]) :-	symbol(Symbols, Output).  
start2(Symbols, [t(a,0,1,r,b), t(b,0,Output,l,c)]) :-	symbol(Symbols, Output).  

refinelist(Dir, [Next|Files], StoreFile) :-
	append(Dir, Next, F1),	append(F1, ".pl", F), append(F1, "-out.pl", F2), 
	string2term(F, InFile), string2term(F2, OutFile),
	refine(InFile, OutFile, StoreFile), !, 
	refinelist(Dir, Files, StoreFile), 
	true. 

refine(Num, GoFile) :-
	format("Refining part ~d~n", [Num]), 
	beaverbase(Dir), filelist(Num, List),
	format("Starting ... ~n", []), 
	refinelist(Dir, List, GoFile). 

refineone(InFile, OutFile, GoFile) :-
	!, open(GoFile, write, Go), !, 
	retractall(ghalts(_)), retractall(gloops(_)), retractall(ggoing(_)), retractall(gblank(_)), retractall(ggrows(_)), retractall(ghypes(_)), !, 
	retractall(records(_)), 
	assert(ghalts(0)), assert(gloops(0)), assert(ggoing(0)), assert(gblank(0)), assert(ggrows(0)), assert(ghypes(0)), !, 
	assert(records([])), !, 
	refine(InFile, OutFile, Go),
	retract(ghalts(Halts)),	retract(gloops(Loops)), retract(ggoing(Going)), retract(gblank(Blank)), retract(ggrows(Grow)), retract(ghypes(Hyp)), 
	format("% Overall statistics are Halt: ~d Loop: ~d Grow: ~d Blank: ~d Going: ~d Hyp: ~d~n", [Halts, Loops, Grow, Blank, Going, Hyp]), 
        pivot(small,MaxPS), pivot(large,MaxPL), nonpivot(small,MaxNS), nonpivot(large, MaxNL), hypmax(small,HMaxS), hypmax(large,HMaxL), smallhist(MaxHS), largehist(MaxHL), 
        format("% Parameters are pivot: ~d and ~d, nonpivot: ~d and ~d hypmax: ~d and ~d, maxhist ~d and ~d~n", [MaxPS, MaxPL, MaxNS, MaxNL, HMaxS, HMaxL, MaxHS, MaxHL]), 
	retract(records(R)), 	
	printlist(R), 
	close(Go). 

% So we know what to refine ... should improve this!
filelist(1, ["b511","b512","b513","b514"]). 
filelist(2, ["b521","b522","b523","b524","b525","b526","b527","b528","b529","b5210","b5211","b5212","b5213","b5214","b5215"]). 
filelist(3, ["b531","b532"]). 
filelist(4, ["b541","b542","b543","b544","b545","b546","b547"]). 
filelist(5, ["b551","b552","b553","b554","b555","b556","b557","b558","b559","b5510",
            "b5511","b5512","b5513","b5514","b5515","b5516","b5517","b5518","b5519","b5520","b5521","b5522","b5523","b5524"]).
filelist(6, ["b561","b562","b563","b564","b565","b566","b567","b568","b569","b5610",
            "b5611","b5612","b5613","b5614","b5615","b5616","b5617","b5618","b5619","b5620",
	    "b5621","b5622","b5623","b5624","b5625","b5626","b5627","b5628","b5629","b5630","b5631", "b5632",
	    "b5633","b5634","b5635","b5636","b5637"]).
filelist(7, ["b571","b572","b573","b574","b575","b576","b577","b578","b579","b5710",
            "b5711","b5712","b5713","b5714","b5715","b5716", "b5717","b5718","b5719","b5720","b5721"]). 
filelist(8, ["b581","b582","b583","b584","b585","b586","b587","b588","b589","b5810",
              "b5811","b5812","b5813","b5814","b5815","b5816","b5817","b5818", "b5819", "b5820",
              "b5821","b5822","b5823","b5824","b5825","b5826","b5827","b5828", "b5829", "b5830",
              "b5831","b5832","b5833","b5834","b5835","b5836","b5837","b5838", "b5839", "b5840",
	      "b5841","b5842","b5843","b5844","b5845","b5846" ]).

refine(InFile, OutFile, GoFile) :-
	retractall(halts(_)), retractall(loops(_)), retractall(going(_)), retractall(blank(_)), retractall(grows(_)), retractall(hypes(_)), 
	assert(halts(0)), assert(loops(0)), assert(going(0)), assert(blank(0)), assert(grows(0)), assert(hypes(0)), 
	open(InFile, read, Input), 
	tell(OutFile), 
	processfile(Input, GoFile), !, 
	close(Input),
	retract(halts(Halts)), 	retract(loops(Loops)), retract(going(Going)), retract(blank(Blank)), retract(grows(Grow)), retract(hypes(Hyp)), 
	format("% Halt: ~d Loop: ~d Grow: ~d Blank: ~d Going: ~d Hyp: ~d~n", [Halts, Loops, Grow, Blank, Going, Hyp]), 
        pivot(small,MaxPS), pivot(large,MaxPL), nonpivot(small,MaxNS), nonpivot(large, MaxNL), hypmax(small,HMaxS), hypmax(large,HMaxL), smallhist(MaxHS), largehist(MaxHL), 
        format("% Parameters are pivot: ~d and ~d, nonpivot: ~d and ~d hypmax: ~d and ~d, maxhist ~d and ~d~n", [MaxPS, MaxPL, MaxNS, MaxNL, HMaxS, HMaxL, MaxHS, MaxHL]), 
        records(R), printlist(R), 
	told,
	retract(ghalts(GH)), retract(gloops(GL)), retract(ggoing(GO)), retract(gblank(GB)), retract(ggrows(GG)),  retract(ghypes(GHyp)),   
	GH1 is GH + Halts, GL1 is GL + Loops, GO1 is GO + Going, GB1 is GB + Blank, GG1 is GG + Grow, GHyp1 is Hyp + GHyp, 
	assert(ghalts(GH1)), assert(gloops(GL1)), assert(ggoing(GO1)), assert(gblank(GB1)), assert(ggrows(GG1)),   assert(ghypes(GHyp1)).   

processfile(Input, GoFile) :-
	repeat, 
	read(Input, Term), 
	process_term(Term, GoFile), 
	Term == end_of_file.

process_term(end_of_file, _) :- !. 
process_term(bb(N, Machine, Ones, Hops, Status), GoFile) :- 
	analyse(Machine, Ones, Hops, Status, NewOnes, NewHops, NewStatus), !, 
	bbinternalprint(bb, N, Machine, NewOnes, NewHops, NewStatus),  !, 
	test(GoFile, N, Machine, NewOnes, NewHops, NewStatus),  !, 
	updatestats(NewStatus), !. 

checkmax(M, Ones, Hops) :-
	records(List), 
	\+ member(max(Ones, _, _), List), !, 
	append([max(Ones, M, Hops)], List, NewList),
	retract(records(_)), assert(records(NewList)), !. 
checkmax(_M, Ones, Hops) :-
	records(List), 
	member(max(Ones, _M1, H1), List),
	H1 >= Hops, !.
checkmax(M, Ones, Hops) :-
	records(List), 
	member(max(Ones, M1, H1), List),
	H1 < Hops,!, 
	delete(List, max(Ones, M1, H1), NL),
	append([max(Ones, M, Hops)], NL, NewList), 
	retract(records(_)), assert(records(NewList)), !. 

checkmin(M, Ones, Hops) :-
	records(List), 
	\+ member(min(Ones, _, _), List),!, 
	append([min(Ones, M, Hops)], List, NewList),
	retract(records(_)), assert(records(NewList)), !. 
checkmin(_M, Ones, Hops) :-
	records(List), 
	member(min(Ones, _M1, H1), List),
	H1 =< Hops, !.
checkmin(M, Ones, Hops) :-
	records(List), 
	member(min(Ones, M1, H1), List),
	H1 > Hops,!, 
	delete(List, min(Ones, M1, H1), NL),
	append([min(Ones, M, Hops)], NL, NewList), 
	retract(records(_)), assert(records(NewList)), !. 

refineall(GoingFile) :-
	open(GoingFile, write, GoFile), 
	retractall(ghalts(_)), retractall(gloops(_)), retractall(ggoing(_)), retractall(gblank(_)), retractall(ggrows(_)), retractall(ghypes(_)), 
	retractall(records(_)), 
	assert(ghalts(0)), assert(gloops(0)), assert(ggoing(0)), assert(gblank(0)), assert(ggrows(0)), assert(ghypes(0)), 
	assert(records([])), 
        refine(1, GoFile), !, format("Done 1~n", []), 
	refine(2, GoFile), !, format("Done 2~n", []), 
	refine(3, GoFile), !, format("Done 3~n", []), 
	refine(4, GoFile), !, format("Done 4~n", []), 
	refine(5, GoFile), !, format("Done 5~n", []), 
	refine(6, GoFile), !, format("Done 6~n", []), 
	refine(7, GoFile), !, format("Done 7~n", []),  
	refine(8, GoFile), !, format("Done 8~n", []), 
	retract(ghalts(Halts)),	retract(gloops(Loops)), retract(ggoing(Going)), retract(gblank(Blank)), retract(ggrows(Grow)), retract(ghypes(Hype)), 
	retract(records(R)), 
	format("% Overall statistics are Halt: ~d Loop: ~d Grow: ~d Blank: ~d Going: ~d Hyp: ~d~n", [Halts, Loops, Grow, Blank, Going, Hype]), 
        pivot(small,MaxPS), pivot(large,MaxPL), nonpivot(small,MaxNS), nonpivot(large, MaxNL), hypmax(small,HMaxS), hypmax(large,HMaxL), smallhist(MaxHS), largehist(MaxHL), 
        format("% Parameters are pivot: ~d and ~d, nonpivot: ~d and ~d hypmax: ~d and ~d, maxhist ~d and ~d~n", [MaxPS, MaxPL, MaxNS, MaxNL, HMaxS, HMaxL, MaxHS, MaxHL]), 
	printlist(R), 
	close(GoFile).

test(_Going, _N, Machine, Ones, Hops, halts) :- !, checkmax(Machine, Ones, Hops), !, checkmin(Machine, Ones, Hops), !. 
test(_Going, _N, _Machine, _Ones, _Hops, halts(_)) :- !.
test(_Going, _N,_Machine, _Ones, _Hops, loops) :- !.
test(_Going, _N,_Machine, _Ones, _Hops, meander) :- !.
test(_Going, _N,_Machine, _Ones, _Hops, loops(_)) :- !. 
test(_Going, _N,_Machine, _Ones, _Hops, blank) :- !.
test(Going, N, Machine, Ones, Hops, hyp(H)) :- !,
	!, display(Going, bb(N, Machine, Ones, Hops, hyp(H))), put_char(Going, '.'), nl(Going), !. 
test(Going, N, Machine, Ones, Hops, hyp(H1,H2,H3)) :- !,
	!, display(Going, bb(N, Machine, Ones, Hops, hyp(H1,H2,H3))), put_char(Going, '.'), nl(Going), !. 
test(Going, N, Machine, Ones, Hops, going) :-
	!, display(Going, bb(N, Machine, Ones, Hops, going)), put_char(Going, '.'), nl(Going), !. 
test(_Going, N, Machine, Ones, Hops, halts(T)) :- 
	!, display(Going, bb(N, Machine, Ones, Hops, halts(T))), put_char(Going, '.'), nl(Going), !. 

stats(Machine, Ones, Hops, halts) :- !, checkmax(Machine, Ones, Hops), !, checkmin(Machine, Ones, Hops), !. 
stats(_Machine, _Ones, _Hops, halts(_)) :- !.
stats(_Machine, _Ones, _Hops, loops) :- !.
stats(_Machine, _Ones, _Hops, meander) :- !.
stats(_Machine, _Ones, _Hops, loops(_)) :- !. 
stats(_Machine, _Ones, _Hops, blank) :- !.
stats(_Machine, _Ones, _Hops, hyp(_H)) :- !.
stats(_Machine, _Ones, _Hops, hyp(_H1,_H2,_H3)) :- !.
stats(_Machine, _Ones, _Hops, going) :- !.


