1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2% A Learning Engine for Proposing Hypotheses                              %
    3%                                                                         %
    4% A L E P H                                                               %
    5% Version 5    (last modified: Sun Mar 11 03:25:37 UTC 2007)              %
    6%                                                                         %
    7% This is the source for Aleph written and maintained                     %
    8% by Ashwin Srinivasan (ashwin@comlab.ox.ac.uk)                           %
    9%                                                                         %
   10%                                                                         %
   11% It was originally written to run with the Yap Prolog Compiler           %
   12% Yap can be found at: http://sourceforge.net/projects/yap/               %
   13% Yap must be compiled with -DDEPTH_LIMIT=1                               %
   14%                                                                         %
   15% It should also run with SWI Prolog, although performance may be         %
   16% sub-optimal.                                                            %
   17%                                                                         %
   18% If you obtain this version of Aleph and have not already done so        %
   19% please subscribe to the Aleph mailing list. You can do this by          %
   20% mailing majordomo@comlab.ox.ac.uk with the following command in the     %
   21% body of the mail message: subscribe aleph                               %
   22%                                                                         %
   23% Aleph is freely available for academic purposes.                        %
   24% If you intend to use it for commercial purposes then                    %
   25% please contact Ashwin Srinivasan first.                                 %
   26%                                                                         %
   27% A simple on-line manual is available on the Web at                      %
   28% www.comlab.ox.ac.uk/oucl/research/areas/machlearn/Aleph/index.html      %
   29%                                                                         %
   30%                                                                         %
   31%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   32 
   33
   34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   35% C O M P I L E R   S P E C I F I C
   36
   37
   38prolog_type(yap):-
   39	predicate_property(yap_flag(_,_),built_in), !.
   40prolog_type(swi).
   41
   42init(yap):-
   43	source,
   44	system_predicate(false,false), hide(false),
   45	style_check(single_var),
   46	% yap_flag(profiling,on),
   47	assert_static((aleph_random(X):- X is random)),
   48	(predicate_property(alarm(_,_,_),built_in) ->
   49		assert_static((remove_alarm(X):- alarm(0,_,_)));
   50		assert_static(alarm(_,_,_)),
   51		assert_static(remove_alarm(_))),
   52	assert_static((aleph_consult(F):- consult(F))),
   53	assert_static((aleph_reconsult(F):- reconsult(F))),
   54        (predicate_property(thread_local(_),built_in) -> true;
   55		assert_static(thread_local(_))),
   56	assert_static(broadcast(_)),
   57	assert_static((aleph_background_predicate(Lit):-
   58				predicate_property(Lit,P),
   59				((P = static); (P = dynamic); (P = built_in)), !)),
   60	(predicate_property(delete_file(_),built_in) -> true;
   61		assert_static(delete_file(_))).
   62
   63init(swi):-
   64	redefine_system_predicate(false),
   65	style_check(+singleton),
   66	style_check(-discontiguous),
   67	dynamic(false/0),
   68	dynamic(example/3),
   69	assert((aleph_random(X):- I = 1000000, X is float(random(I-1))/float(I))),
   70	assert((gc:- garbage_collect)),
   71	assert((depth_bound_call(G,L):-
   72			call_with_depth_limit(G,L,R),
   73			R \= depth_limit_exceeded)),
   74	(predicate_property(numbervars(_,_,_),built_in) -> true;
   75		assert((numbervars(A,B,C):- numbervars(A,'$VAR',B,C)))),
   76	assert((assert_static(X):- assert(X))),
   77	assert((system(X):- shell(X))),
   78	assert((exists(X):- exists_file(X))),
   79	assert((aleph_reconsult(F):- consult(F))),
   80	assert((aleph_consult(X):- aleph_open(X,read,S), repeat,
   81			read(S,F), (F = end_of_file -> close(S), !;
   82					assertz(F),fail))),
   83	use_module(library(broadcast)),
   84	use_module(library(time)),
   85        (predicate_property(thread_local(_),built_in) -> true;
   86		assert(thread_local(_))),
   87	assert((aleph_background_predicate(Lit):-
   88				predicate_property(Lit,P),
   89				((P=interpreted);(P=built_in)), ! )),
   90	(predicate_property(delete_file(_),built_in) -> true;
   91		assert_static(delete_file(_))).
   92:- if(current_prolog_flag(dialect,swi)). 
   93:- use_module(library(arithmetic)). 
   94:- arithmetic_function(inf/0). 
   95:- init(swi).   96inf(1e10).
   97:- else.   98:- init(yap).   99:- endif. 
  100
  101
  102%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  103% A L E P H
  104
  105
  106aleph_version(5).
  107aleph_version_date('Sun Mar 11 03:25:37 UTC 2007').
  108aleph_manual('http://www.comlab.ox.ac.uk/oucl/groups/machlearn/Aleph/index.html').
  109
  110:- op(500,fy,#).  111:- op(500,fy,*).  112:- op(900,xfy,because).  113
  114:- dynamic '$aleph_feature'/2.  115:- dynamic '$aleph_global'/2.  116:- dynamic '$aleph_good'/3.  117
  118:- dynamic '$aleph_local'/2.  119
  120:- dynamic '$aleph_sat'/2.  121:- dynamic '$aleph_sat_atom'/2.  122:- dynamic '$aleph_sat_ovars'/2.  123:- dynamic '$aleph_sat_ivars'/2.  124:- dynamic '$aleph_sat_varsequiv'/2.  125:- dynamic '$aleph_sat_varscopy'/3.  126:- dynamic '$aleph_sat_terms'/4.  127:- dynamic '$aleph_sat_vars'/4.  128:- dynamic '$aleph_sat_litinfo'/6.  129
  130:- dynamic '$aleph_search_cache'/1.  131:- dynamic '$aleph_search_prunecache'/1.  132:- dynamic '$aleph_search'/2.  133:- dynamic '$aleph_search_seen'/2.  134:- dynamic '$aleph_search_expansion'/4.  135:- dynamic '$aleph_search_gain'/4.  136:- dynamic '$aleph_search_node'/8.  137
  138:- dynamic '$aleph_link_vars'/2.  139:- dynamic '$aleph_has_vars'/3.  140:- dynamic '$aleph_has_ovar'/4.  141:- dynamic '$aleph_has_ivar'/4.  142:- dynamic '$aleph_determination'/2.  143
  144:- thread_local('$aleph_search_cache'/1).  145:- thread_local('$aleph_search_prunecache'/1).  146:- thread_local('$aleph_search'/2).  147:- thread_local('$aleph_search_seen'/2).  148:- thread_local('$aleph_search_expansion'/4).  149:- thread_local('$aleph_search_gain'/4).  150:- thread_local('$aleph_search_node'/8).  151
  152
  153:- multifile false/0.  154:- multifile prune/1.  155:- multifile refine/2.  156:- multifile cost/3.  157:- multifile prove/2.  158
  159%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  160% C O N S T R U C T   B O T T O M
  161
  162% get_atoms(+Preds,+Depth,+MaxDepth,+Last,-LastLit)
  163% layered generation of ground atoms to add to bottom clause
  164%	Preds is list of PName/Arity entries obtained from the determinations
  165%	Depth is current variable-chain depth
  166%	MaxDepth is maximum allowed variable chain depth (i setting)
  167%	Last is last atom number so far
  168%	Lastlit is atom number after all atoms to MaxDepth have been generated
  169get_atoms([],_,_,Last,Last):- !.
  170get_atoms(Preds,Depth,MaxDepth,Last,LastLit):-
  171	Depth =< MaxDepth,
  172	Depth0 is Depth - 1,
  173	'$aleph_sat_terms'(_,Depth0,_,_),	% new terms generated ?
  174	!,
  175	get_atoms1(Preds,Depth,MaxDepth,Last,Last1),
  176	Depth1 is Depth + 1,
  177	get_atoms(Preds,Depth1,MaxDepth,Last1,LastLit).
  178get_atoms(_,_,_,Last,Last).
  179
  180% auxiliary predicate used by get_atoms/5
  181get_atoms1([],_,_,Last,Last).
  182get_atoms1([Pred|Preds],Depth,MaxDepth,Last,LastLit):-
  183	gen_layer(Pred,Depth),
  184	flatten(Depth,MaxDepth,Last,Last1),
  185	get_atoms1(Preds,Depth,MaxDepth,Last1,LastLit).
  186
  187% flatten(+Depth,+MaxDepth,+Last,-LastLit)
  188% flatten a set of ground atoms by replacing all in/out terms with variables
  189%	constants are wrapped in a special term called aleph_const(...)
  190%	eg suppose p/3 had modes p(+char,+char,#int)
  191%	then p(a,a,3) becomes p(X,X,aleph_const(3))
  192% ground atoms to be flattened are assumed to be in the i.d.b atoms
  193% vars and terms are actually integers which are stored in vars/terms databases
  194%	so eg above actually becomes p(1,1,aleph_const(3)).
  195%	where variable 1 stands for term 2 (say) which in turn stands for a
  196%	Depth is current variable-chain depth
  197%	MaxDepth is maximum allowed variable chain depth (i setting)
  198%	Last is last atom number so far
  199%	Lastlit is atom number after ground atoms here have been flattened
  200% If permute_bottom is set to true, then the order of ground atoms is
  201% shuffled. The empirical utility of doing this has been investigated by
  202% P. Schorn in "Random Local Bottom Clause Permutations for Better Search Space
  203% Exploration in Progol-like ILP Systems.", 16th International Conference on
  204% ILP (ILP 2006).
  205flatten(Depth,MaxDepth,Last,Last1):-
  206	retractall('$aleph_local'(flatten_num,_)),
  207	asserta('$aleph_local'(flatten_num,Last)),
  208	'$aleph_sat_atom'(_,_), !,
  209	(setting(permute_bottom,Permute) -> true; Permute = false),
  210	flatten_atoms(Permute,Depth,MaxDepth,Last1).
  211flatten(_,_,_,Last):-
  212	retract('$aleph_local'(flatten_num,Last)), !.
  213
  214flatten_atoms(true,Depth,MaxDepth,Last1):-
  215	findall(L-M,retract('$aleph_sat_atom'(L,M)),LitModes),
  216	aleph_rpermute(LitModes,PLitModes),
  217	aleph_member(Lit1-Mode,PLitModes),
  218	retract('$aleph_local'(flatten_num,LastSoFar)),
  219	(Lit1 = not(Lit) -> Negated = true; Lit = Lit1, Negated = false),
  220	flatten_atom(Depth,MaxDepth,Lit,Negated,Mode,LastSoFar,Last1),
  221	asserta('$aleph_local'(flatten_num,Last1)),
  222	fail.
  223flatten_atoms(false,Depth,MaxDepth,Last1):-
  224	repeat,
  225	retract('$aleph_sat_atom'(Lit1,Mode)),
  226	retract('$aleph_local'(flatten_num,LastSoFar)),
  227	(Lit1 = not(Lit) -> Negated = true; Lit = Lit1, Negated = false),
  228	flatten_atom(Depth,MaxDepth,Lit,Negated,Mode,LastSoFar,Last1),
  229	asserta('$aleph_local'(flatten_num,Last1)),
  230	('$aleph_sat_atom'(_,_) ->
  231			fail;
  232			retract('$aleph_local'(flatten_num,Last1))), !.
  233flatten_atoms(_,_,_,Last):-
  234	retract('$aleph_local'(flatten_num,Last)), !.
  235
  236
  237% flatten_atom(+Depth,+Depth1,+Lit,+Negated,+Mode,+Last,-Last1)
  238%	update lits database by adding ``flattened atoms''. This involves:
  239%	replacing ground terms at +/- positions in Lit with variables
  240%	and wrapping # positions in Lit within a special term stucture
  241%	Mode contains actual mode and term-place numbers and types for +/-/# 
  242%	Last is the last literal number in the lits database at present
  243%	Last1 is the last literal number after the update
  244flatten_atom(Depth,Depth1,Lit,Negated,Mode,Last,Last1):-
  245	arg(3,Mode,O), arg(4,Mode,C),
  246	integrate_args(Depth,Lit,O),
  247	integrate_args(Depth,Lit,C),
  248	(Depth = Depth1 -> CheckOArgs = true; CheckOArgs = false),
  249	flatten_lits(Lit,CheckOArgs,Depth,Negated,Mode,Last,Last1).
  250
  251% variabilise literals by replacing terms with variables
  252% if var splitting is on then new equalities are introduced into bottom clause
  253% if at final i-layer, then literals with o/p args that do not contain at least
  254% 	one output var from head are discarded
  255flatten_lits(Lit,CheckOArgs,Depth,Negated,Mode,Last,_):-
  256	functor(Lit,Name,Arity),
  257	asserta('$aleph_local'(flatten_lits,Last)),
  258	Depth1 is Depth - 1,
  259	functor(OldFAtom,Name,Arity),
  260	flatten_lit(Lit,Mode,OldFAtom,_,_),
  261	functor(FAtom,Name,Arity),
  262	apply_equivs(Depth1,Arity,OldFAtom,FAtom),
  263	retract('$aleph_local'(flatten_lits,OldLast)),
  264	(CheckOArgs = true -> 
  265		arg(3,Mode,Out),
  266		get_vars(FAtom,Out,OVars),
  267		(in_path(OVars) ->
  268			add_new_lit(Depth,FAtom,Mode,OldLast,Negated,NewLast);
  269			NewLast = OldLast) ;
  270		add_new_lit(Depth,FAtom,Mode,OldLast,Negated,NewLast)),
  271	asserta('$aleph_local'(flatten_lits,NewLast)),
  272	fail.
  273flatten_lits(_,_,_,_,_,_,Last1):-
  274	retract('$aleph_local'(flatten_lits,Last1)).
  275
  276
  277% flatten_lit(+Lit,+Mode,+FAtom,-IVars,-OVars)
  278% variabilise Lit as FAtom
  279%	Mode contains actual mode and 
  280%	In, Out, Const positions as term-place numbers with types
  281% 	replace ground terms with integers denoting variables
  282%	or special terms denoting constants
  283% 	variable numbers arising from variable splits are disallowed
  284%	returns Input and Output variable numbers
  285flatten_lit(Lit,mode(Mode,In,Out,Const),FAtom,IVars,OVars):-
  286	functor(Mode,_,Arity),
  287	once(copy_modeterms(Mode,FAtom,Arity)),
  288	flatten_vars(In,Lit,FAtom,IVars),
  289	flatten_vars(Out,Lit,FAtom,OVars),
  290	flatten_consts(Const,Lit,FAtom).
  291
  292% flatten_vars(+TPList,+Lit,+FAtom,-Vars):-
  293% FAtom is Lit with terms-places in TPList replaced by variables
  294flatten_vars([],_,_,[]).
  295flatten_vars([Pos/Type|Rest],Lit,FAtom,[Var|Vars]):-
  296	tparg(Pos,Lit,Term),
  297	'$aleph_sat_terms'(TNo,_,Term,Type),
  298	'$aleph_sat_vars'(Var,TNo,_,_),
  299	\+('$aleph_sat_varscopy'(Var,_,_)),
  300	tparg(Pos,FAtom,Var),
  301	flatten_vars(Rest,Lit,FAtom,Vars).
  302
  303% replace a list of terms at places marked by # in the modes
  304% with a special term structure denoting a constant
  305flatten_consts([],_,_).
  306flatten_consts([Pos/_|Rest],Lit,FAtom):-
  307	tparg(Pos,Lit,Term),
  308	tparg(Pos,FAtom,aleph_const(Term)),
  309	flatten_consts(Rest,Lit,FAtom).
  310
  311% in_path(+ListOfOutputVars)
  312% check to avoid generating useless literals in the last i layer
  313in_path(OVars):-
  314	'$aleph_sat'(hovars,Vars), !,
  315	(Vars=[];OVars=[];intersects(Vars,OVars)).
  316in_path(_).
  317
  318% update_equivs(+VariableEquivalences,+IDepth)
  319% update variable equivalences created at a particular i-depth
  320% is non-empty only if variable splitting is allowed
  321update_equivs([],_):- !.
  322update_equivs(Equivs,Depth):-
  323	retract('$aleph_sat_varsequiv'(Depth,Eq1)), !,
  324	update_equiv_lists(Equivs,Eq1,Eq2),
  325	asserta('$aleph_sat_varsequiv'(Depth,Eq2)).
  326update_equivs(Equivs,Depth):-
  327	Depth1 is Depth - 1,
  328	get_equivs(Depth1,Eq1),
  329	update_equiv_lists(Equivs,Eq1,Eq2),
  330	asserta('$aleph_sat_varsequiv'(Depth,Eq2)).
  331
  332update_equiv_lists([],E,E):- !.
  333update_equiv_lists([Var/E1|Equivs],ESoFar,E):-
  334	aleph_delete(Var/E2,ESoFar,ELeft), !,
  335	update_list(E1,E2,E3),
  336	update_equiv_lists(Equivs,[Var/E3|ELeft],E).
  337update_equiv_lists([Equiv|Equivs],ESoFar,E):-
  338	update_equiv_lists(Equivs,[Equiv|ESoFar],E).
  339
  340% get variable equivalences at a particular depth
  341% recursively descend to greatest depth below this for which equivs exist
  342% also returns the database reference of entry
  343get_equivs(Depth,[]):-
  344	Depth < 0, !.
  345get_equivs(Depth,Equivs):-
  346	'$aleph_sat_varsequiv'(Depth,Equivs), !.
  347get_equivs(Depth,E):-
  348	Depth1 is Depth - 1,
  349	get_equivs(Depth1,E).
  350
  351% apply equivalences inherited from Depth to a flattened literal
  352% if no variable splitting, then succeeds only once
  353apply_equivs(Depth,Arity,Old,New):-
  354	get_equivs(Depth,Equivs),
  355	rename(Arity,Equivs,[],Old,New).
  356
  357% rename args using list of Var/Equivalences
  358rename(_,[],_,L,L):- !.
  359rename(0,_,_,_,_):- !.
  360rename(Pos,Equivs,Subst0,Old,New):-
  361        arg(Pos,Old,OldVar),
  362        aleph_member(OldVar/Equiv,Equivs), !,
  363        aleph_member(NewVar,Equiv),
  364        arg(Pos,New,NewVar),
  365        Pos1 is Pos - 1,
  366        rename(Pos1,Equivs,[OldVar/NewVar|Subst0],Old,New).
  367rename(Pos,Equivs,Subst0,Old,New):-
  368        arg(Pos,Old,OldVar),
  369        (aleph_member(OldVar/NewVar,Subst0) ->
  370                arg(Pos,New,NewVar);
  371                arg(Pos,New,OldVar)),
  372        Pos1 is Pos - 1,
  373        rename(Pos1,Equivs,Subst0,Old,New).
  374
  375
  376% add a new literal to lits database
  377% performs variable splitting if splitvars is set to true
  378add_new_lit(Depth,FAtom,Mode,OldLast,Negated,NewLast):-
  379	arg(1,Mode,M),
  380	functor(FAtom,Name,Arity),
  381	functor(SplitAtom,Name,Arity),
  382	once(copy_modeterms(M,SplitAtom,Arity)),
  383	arg(2,Mode,In), arg(3,Mode,Out), arg(4,Mode,Const),
  384        split_vars(Depth,FAtom,In,Out,Const,SplitAtom,IVars,OVars,Equivs),
  385        update_equivs(Equivs,Depth),
  386        add_lit(OldLast,Negated,SplitAtom,In,Out,IVars,OVars,LitNum),
  387        insert_eqs(Equivs,Depth,LitNum,NewLast), !.
  388
  389% modify the literal database: check if performing lazy evaluation
  390% of bottom clause, and update input and output terms in literal
  391add_lit(Last,Negated,FAtom,I,O,_,_,Last):-
  392	setting(construct_bottom,CBot),
  393	(CBot = false ; CBot = reduction), 
  394	(Negated = true -> Lit = not(FAtom); Lit = FAtom),
  395	'$aleph_sat_litinfo'(_,0,Lit,I,O,_), !.
  396add_lit(Last,Negated,FAtom,In,Out,IVars,OVars,LitNum):-
  397	LitNum is Last + 1,
  398	update_iterms(LitNum,IVars),
  399	update_oterms(LitNum,OVars,[],Dependents),
  400	add_litinfo(LitNum,Negated,FAtom,In,Out,Dependents),
  401	assertz('$aleph_sat_ivars'(LitNum,IVars)),
  402	assertz('$aleph_sat_ovars'(LitNum,OVars)), !.
  403
  404
  405% update lits database after checking that the atom does not exist
  406% used during updates of lit database by lazy evaluation
  407update_lit(LitNum,true,FAtom,I,O,D):-
  408	'$aleph_sat_litinfo'(LitNum,0,not(FAtom),I,O,D), !.
  409update_lit(LitNum,false,FAtom,I,O,D):-
  410	'$aleph_sat_litinfo'(LitNum,0,FAtom,I,O,D), !.
  411update_lit(LitNum,Negated,FAtom,I,O,D):-
  412	gen_nlitnum(LitNum),
  413	add_litinfo(LitNum,Negated,FAtom,I,O,D), 
  414	get_vars(FAtom,I,IVars),
  415	get_vars(FAtom,O,OVars),
  416	assertz('$aleph_sat_ivars'(LitNum,K,IVars)),
  417	assertz('$aleph_sat_ovars'(LitNum,K,OVars)), !.
  418
  419% add a literal to lits database without checking
  420add_litinfo(LitNum,true,FAtom,I,O,D):-
  421	!,
  422	assertz('$aleph_sat_litinfo'(LitNum,0,not(FAtom),I,O,D)).
  423add_litinfo(LitNum,_,FAtom,I,O,D):-
  424	assertz('$aleph_sat_litinfo'(LitNum,0,FAtom,I,O,D)).
  425	
  426% update database with input terms of literal
  427update_iterms(_,[]).
  428update_iterms(LitNum,[VarNum|Vars]):-
  429	retract('$aleph_sat_vars'(VarNum,TNo,I,O)),
  430	update(I,LitNum,NewI),
  431	asserta('$aleph_sat_vars'(VarNum,TNo,NewI,O)),
  432	update_dependents(LitNum,O),
  433	update_iterms(LitNum,Vars).
  434
  435% update database with output terms of literal
  436% return list of dependent literals
  437update_oterms(_,[],Dependents,Dependents).
  438update_oterms(LitNum,[VarNum|Vars],DSoFar,Dependents):-
  439	retract('$aleph_sat_vars'(VarNum,TNo,I,O)),
  440	update(O,LitNum,NewO),
  441	asserta('$aleph_sat_vars'(VarNum,TNo,I,NewO)),
  442	update_list(I,DSoFar,D1),
  443	update_oterms(LitNum,Vars,D1,Dependents).
  444
  445% update Dependent list of literals with LitNum
  446update_dependents(_,[]).
  447update_dependents(LitNum,[Lit|Lits]):-
  448	retract('$aleph_sat_litinfo'(Lit,Depth,Atom,ITerms,OTerms,Dependents)),
  449	update(Dependents,LitNum,NewD),
  450	asserta('$aleph_sat_litinfo'(Lit,Depth,Atom,ITerms,OTerms,NewD)),
  451	update_dependents(LitNum,Lits).
  452
  453% update dependents of head with literals that are simply generators
  454% 	that is, literals that require no input args
  455update_generators:-
  456	findall(L,('$aleph_sat_litinfo'(L,_,_,[],_,_),L>1),GList),
  457	GList \= [], !,
  458	retract('$aleph_sat_litinfo'(1,Depth,Lit,I,O,D)),
  459	aleph_append(D,GList,D1),
  460	asserta('$aleph_sat_litinfo'(1,Depth,Lit,I,O,D1)).
  461update_generators.
  462
  463% mark literals 
  464mark_lits(Lits):-
  465	aleph_member(Lit,Lits),
  466	asserta('$aleph_local'(marked,Lit/0)),
  467	fail.
  468mark_lits(_).
  469	
  470% recursively mark literals with minimum depth to bind output vars in head
  471mark_lits([],_,_).
  472mark_lits(Lits,OldVars,Depth):-
  473	mark_lits(Lits,Depth,true,[],Predecessors,OldVars,NewVars),
  474	aleph_delete_list(Lits,Predecessors,P1),
  475	Depth1 is Depth + 1,
  476	mark_lits(P1,NewVars,Depth1).
  477
  478mark_lits([],_,_,P,P,V,V).
  479mark_lits([Lit|Lits],Depth,GetPreds,PSoFar,P,VSoFar,V):-
  480	retract('$aleph_local'(marked,Lit/Depth0)), !,
  481	(Depth < Depth0 ->
  482		mark_lit(Lit,Depth,GetPreds,VSoFar,P1,V2),
  483		update_list(P1,PSoFar,P2),
  484		mark_lits(Lits,Depth,GetPreds,P2,P,V2,V);
  485		asserta('$aleph_local'(marked,Lit/Depth0)),
  486		mark_lits(Lits,Depth,GetPreds,PSoFar,P,VSoFar,V)).
  487mark_lits([Lit|Lits],Depth,GetPreds,PSoFar,P,VSoFar,V):-
  488	mark_lit(Lit,Depth,GetPreds,VSoFar,P1,V2), !,
  489	update_list(P1,PSoFar,P2),
  490	mark_lits(Lits,Depth,GetPreds,P2,P,V2,V).
  491mark_lits([_|Lits],Depth,GetPreds,PSoFar,P,VSoFar,V):-
  492	mark_lits(Lits,Depth,GetPreds,PSoFar,P,VSoFar,V).
  493
  494mark_lit(Lit,Depth,GetPreds,VSoFar,P1,V1):-
  495	retract('$aleph_sat_litinfo'(Lit,_,Atom,I,O,D)),
  496	asserta('$aleph_local'(marked,Lit/Depth)),
  497	asserta('$aleph_sat_litinfo'(Lit,Depth,Atom,I,O,D)),
  498	(GetPreds = false ->
  499		P1 = [],
  500		V1 = VSoFar;
  501		get_vars(Atom,O,OVars),
  502		update_list(OVars,VSoFar,V1),
  503		get_predicates(D,V1,D1),
  504		mark_lits(D1,Depth,false,[],_,VSoFar,_),
  505		get_vars(Atom,I,IVars),
  506		get_predecessors(IVars,[],P1)).
  507
  508% mark lits that produce outputs that are not used by any other literal
  509mark_floating_lits(Lit,Last):-
  510	Lit > Last, !.
  511mark_floating_lits(Lit,Last):-
  512	'$aleph_sat_litinfo'(Lit,_,_,_,O,D),
  513	O \= [],
  514	(D = []; D = [Lit]), !,
  515	asserta('$aleph_local'(marked,Lit/0)),
  516	Lit1 is Lit + 1,
  517	mark_floating_lits(Lit1,Last).
  518mark_floating_lits(Lit,Last):-
  519	Lit1 is Lit + 1,
  520	mark_floating_lits(Lit1,Last).
  521	
  522% mark lits in bottom clause that are specified redundant by user
  523% requires definition of redundant/2 that have distinguished first arg ``bottom''
  524mark_redundant_lits(Lit,Last):-
  525	Lit > Last, !.
  526mark_redundant_lits(Lit,Last):-
  527	get_pclause([Lit],[],Atom,_,_,_),
  528	redundant(bottom,Atom), !,
  529	asserta('$aleph_local'(marked,Lit/0)),
  530	Lit1 is Lit + 1,
  531	mark_redundant_lits(Lit1,Last).
  532mark_redundant_lits(Lit,Last):-
  533	Lit1 is Lit + 1,
  534	mark_redundant_lits(Lit1,Last).
  535
  536% get literals that are linked and do not link to any others (ie predicates)
  537get_predicates([],_,[]).
  538get_predicates([Lit|Lits],Vars,[Lit|T]):-
  539	'$aleph_sat_litinfo'(Lit,_,Atom,I,_,[]),
  540	get_vars(Atom,I,IVars),
  541	aleph_subset1(IVars,Vars), !,
  542	get_predicates(Lits,Vars,T).
  543get_predicates([_|Lits],Vars,T):-
  544	get_predicates(Lits,Vars,T).
  545
  546% get all predecessors in the bottom clause of a set of literals
  547get_predecessors([],[]).
  548get_predecessors([Lit|Lits],P):-
  549	(Lit = 1 -> Pred = [];
  550		get_ivars1(false,Lit,IVars),
  551		get_predecessors(IVars,[],Pred)),
  552	get_predecessors(Pred,PPred),
  553	update_list(Pred,PPred,P1),
  554	get_predecessors(Lits,P2),
  555	update_list(P2,P1,P).
  556
  557% get list of literals in the bottom clause that produce a set of vars
  558get_predecessors([],P,P).
  559get_predecessors([Var|Vars],PSoFar,P):-
  560	'$aleph_sat_vars'(Var,_,_,O),
  561	update_list(O,PSoFar,P1),
  562	get_predecessors(Vars,P1,P).
  563
  564% removal of literals in bottom clause by negative-based reduction.
  565% A greedy strategy is employed, as implemented within the ILP system
  566% Golem (see Muggleton and Feng, "Efficient induction
  567% of logic programs", Inductive Logic Programming, S. Muggleton (ed.),
  568% AFP Press). In this, given a clause H:- B1, B2,...Bn, let Bi be the
  569% first literal s.t. H:-B1,...,Bi covers no more than the allowable number
  570% of negatives. The clause H:- Bi,B1,...,Bi-1 is then reduced. The
  571% process continues until there is no change in the length of a clause
  572% within an iteration. The algorithm is O(n^2).
  573rm_nreduce(Last,N):-
  574	setting(nreduce_bottom,true), !,
  575	get_litnums(1,Last,BottomLits),
  576        '$aleph_global'(atoms,atoms(neg,Neg)),
  577	setting(depth,Depth),
  578	setting(prooftime,Time),
  579	setting(proof_strategy,Proof),
  580	setting(noise,Noise),
  581	neg_reduce(BottomLits,Neg,Last,Depth/Time/Proof,Noise),
  582	get_marked(1,Last,Lits),
  583	length(Lits,N),
  584	p1_message('negative-based removal'), p_message(N/Last).
  585rm_nreduce(_,0).
  586
  587neg_reduce([Head|Body],Neg,Last,DepthTime,Noise):-
  588	get_pclause([Head],[],Clause,TV,_,_),
  589	neg_reduce(Body,Clause,TV,2,Neg,DepthTime,Noise,NewLast),
  590	NewLast \= Last, !,
  591	NewLast1 is NewLast - 1,
  592	aleph_remove_n(NewLast1,[Head|Body],Prefix,[LastLit|Rest]),
  593	mark_lits(Rest),
  594	insert_lastlit(LastLit,Prefix,Lits1),
  595	neg_reduce(Lits1,Neg,NewLast,DepthTime,Noise).
  596neg_reduce(_,_,_,_,_).
  597
  598neg_reduce([],_,_,N,_,_,_,N).
  599neg_reduce([L1|Lits],C,TV,N,Neg,ProofFlags,Noise,LastLit):-
  600	get_pclause([L1],TV,Lit1,TV1,_,_),
  601	extend_clause(C,Lit1,Clause),
  602        prove(ProofFlags,neg,Clause,Neg,NegCover,Count),
  603	Count > Noise, !,
  604	N1 is N + 1,
  605	neg_reduce(Lits,Clause,TV1,N1,NegCover,ProofFlags,Noise,LastLit).
  606neg_reduce(_,_,_,N,_,_,_,N).
  607
  608% insert_lastlit(LastLit,[1|Lits],Lits1):-
  609	% find_last_ancestor(Lits,LastLit,1,2,Last),
  610	% aleph_remove_n(Last,[1|Lits],Prefix,Suffix),
  611	% aleph_append([LastLit|Suffix],Prefix,Lits1).
  612
  613insert_lastlit(LastLit,Lits,Lits1):-
  614	get_predecessors([LastLit],Prefix),
  615	aleph_delete_list(Prefix,Lits,Suffix),
  616	aleph_append([LastLit|Suffix],Prefix,Lits1).
  617
  618	
  619find_last_ancestor([],_,Last,_,Last):- !.
  620find_last_ancestor([Lit|Lits],L,_,LitNum,Last):-
  621	'$aleph_sat_litinfo'(Lit,_,_,_,_,D), 
  622	aleph_member1(L,D), !,
  623	NextLit is LitNum + 1,
  624	find_last_ancestor(Lits,L,LitNum,NextLit,Last).
  625find_last_ancestor([_|Lits],L,Last0,LitNum,Last):-
  626	NextLit is LitNum + 1,
  627	find_last_ancestor(Lits,L,Last0,NextLit,Last).
  628
  629% removal of literals that are repeated because of mode differences
  630rm_moderepeats(_,_):-
  631	'$aleph_sat_litinfo'(Lit1,_,Pred1,_,_,_),
  632	'$aleph_sat_litinfo'(Lit2,_,Pred1,_,_,_),
  633	Lit1 >= 1, Lit2 > Lit1,
  634	retract('$aleph_sat_litinfo'(Lit2,_,Pred1,_,_,_)),
  635	asserta('$aleph_local'(marked,Lit2/0)),
  636	fail.
  637rm_moderepeats(Last,N):-
  638	'$aleph_local'(marked,_), !,
  639	get_marked(1,Last,Lits),
  640	length(Lits,N),
  641	p1_message('repeated literals'), p_message(N/Last),
  642	remove_lits(Lits).
  643rm_moderepeats(_,0).
  644	
  645% removal of symmetric literals
  646rm_symmetric(_,_):-
  647	'$aleph_global'(symmetric,_),
  648	'$aleph_sat_litinfo'(Lit1,_,Pred1,[I1|T1],_,_),
  649	is_symmetric(Pred1,Name,Arity),
  650	get_vars(Pred1,[I1|T1],S1),
  651	'$aleph_sat_litinfo'(Lit2,_,Pred2,[I2|T2],_,_),
  652	Lit1 \= Lit2,
  653	is_symmetric(Pred2,Name,Arity),
  654	Pred1 =.. [_|Args1],
  655	Pred2 =.. [_|Args2],
  656	symmetric_match(Args1,Args2),
  657	get_vars(Pred2,[I2|T2],S2),
  658	equal_set(S1,S2),
  659	asserta('$aleph_local'(marked,Lit2/0)),
  660	retract('$aleph_sat_litinfo'(Lit2,_,Pred2,[I2|T2],_,_)),
  661	fail.
  662rm_symmetric(Last,N):-
  663	'$aleph_local'(marked,_), !,
  664	get_marked(1,Last,Lits),
  665	length(Lits,N),
  666	p1_message('symmetric literals'), p_message(N/Last),
  667	remove_lits(Lits).
  668rm_symmetric(_,0).
  669
  670is_symmetric(not(Pred),not(Name),Arity):-
  671	!,
  672	functor(Pred,Name,Arity),
  673	'$aleph_global'(symmetric,symmetric(Name/Arity)).
  674is_symmetric(Pred,Name,Arity):-
  675	functor(Pred,Name,Arity),
  676	'$aleph_global'(symmetric,symmetric(Name/Arity)).
  677
  678symmetric_match([],[]).
  679symmetric_match([aleph_const(Term)|Terms1],[aleph_const(Term)|Terms2]):-
  680	!,
  681	symmetric_match(Terms1,Terms2).
  682symmetric_match([Term1|Terms1],[Term2|Terms2]):-
  683	integer(Term1), integer(Term2),
  684	symmetric_match(Terms1,Terms2).
  685	
  686% removal of literals that are repeated because of commutativity
  687rm_commutative(_,_):-
  688	'$aleph_global'(commutative,commutative(Name/Arity)),
  689	p1_message('checking commutative literals'), p_message(Name/Arity),
  690	functor(Pred,Name,Arity), functor(Pred1,Name,Arity),
  691	'$aleph_sat_litinfo'(Lit1,_,Pred,[I1|T1],O1,_),
  692        % check for marked literals
  693	% (SWI-Prolog specific: suggested by Vasili Vrubleuski)
  694        \+('$aleph_local'(marked,Lit1/0)),
  695	get_vars(Pred,[I1|T1],S1),
  696	'$aleph_sat_litinfo'(Lit2,_,Pred1,[I2|T2],O2,_),
  697	Lit1 \= Lit2 ,
  698	O1 = O2,
  699	get_vars(Pred1,[I2|T2],S2),
  700	equal_set(S1,S2),
  701	asserta('$aleph_local'(marked,Lit2/0)),
  702	retract('$aleph_sat_litinfo'(Lit2,_,Pred1,[I2|T2],_,_)),
  703	fail.
  704rm_commutative(Last,N):-
  705	'$aleph_local'(marked,_), !,
  706	get_marked(1,Last,Lits),
  707	length(Lits,N),
  708	p1_message('commutative literals'), p_message(N/Last),
  709	remove_lits(Lits).
  710rm_commutative(_,0).
  711
  712% recursive marking of literals that do not contribute to establishing
  713% variable chains to output vars in the head
  714% or produce outputs that are not used by any literal
  715% controlled by setting flag check_useless
  716rm_uselesslits(_,0):-
  717	setting(check_useless,false), !.
  718rm_uselesslits(Last,N):-
  719	'$aleph_sat'(hovars,OVars),
  720	OVars \= [], !,
  721	get_predecessors(OVars,[],P),
  722	'$aleph_sat'(hivars,IVars),
  723	mark_lits(P,IVars,0),
  724	get_unmarked(1,Last,Lits),
  725	length(Lits,N),
  726	p1_message('useless literals'), p_message(N/Last),
  727	remove_lits(Lits).
  728rm_uselesslits(_,0).
  729
  730% call user-defined predicate redundant/2 to remove redundant
  731% literals from bottom clause. Redundancy checking only done on request
  732rm_redundant(_,0):-
  733	setting(check_redundant,false), !.
  734rm_redundant(Last,N):-
  735	mark_redundant_lits(1,Last),
  736	get_marked(1,Last,Lits),
  737	length(Lits,N),
  738	p1_message('redundant literals'), p_message(N/Last),
  739	remove_lits(Lits).
  740
  741% get a list of unmarked literals
  742get_unmarked(Lit,Last,[]):-
  743	Lit > Last, !.
  744get_unmarked(Lit,Last,Lits):-
  745	retract('$aleph_local'(marked,Lit/_)), !,
  746	Next is Lit + 1,
  747	get_unmarked(Next,Last,Lits).
  748get_unmarked(Lit,Last,[Lit|Lits]):-
  749	retract('$aleph_sat_litinfo'(Lit,_,_,_,_,_)), !,
  750	Next is Lit + 1,
  751	get_unmarked(Next,Last,Lits).
  752get_unmarked(Lit,Last,Lits):-
  753	Next is Lit + 1,
  754	get_unmarked(Next,Last,Lits).
  755
  756% get a list of marked literals
  757get_marked(Lit,Last,[]):-
  758	Lit > Last, !.
  759get_marked(Lit,Last,[Lit|Lits]):-
  760	retract('$aleph_local'(marked,Lit/_)), !,
  761	(retract('$aleph_sat_litinfo'(Lit,_,_,_,_,_)) ->
  762		true;
  763		true),
  764	Next is Lit + 1,
  765	get_marked(Next,Last,Lits).
  766get_marked(Lit,Last,Lits):-
  767	Next is Lit + 1,
  768	get_marked(Next,Last,Lits).
  769
  770% update descendent lists of literals by removing useless literals
  771remove_lits(L):-
  772	retract('$aleph_sat_litinfo'(Lit,Depth,A,I,O,D)), 
  773	aleph_delete_list(L,D,D1),
  774	asserta('$aleph_sat_litinfo'(Lit,Depth,A,I,O,D1)),
  775	fail.
  776remove_lits(_).
  777
  778% generate a new literal at depth Depth: forced backtracking will give all lits
  779gen_layer(Name/Arity,Depth):-
  780	(Name/Arity = (not)/1 ->
  781		'$aleph_global'(modeb,modeb(NSucc,not(Mode))),
  782		functor(Mode,Name1,Arity1),
  783		functor(Lit1,Name1,Arity1),
  784		once(copy_modeterms(Mode,Lit1,Arity1)),
  785		Lit = not(Lit1);
  786		functor(Mode,Name,Arity),
  787		functor(Lit,Name,Arity),
  788		'$aleph_global'(modeb,modeb(NSucc,Mode)),
  789		once(copy_modeterms(Mode,Lit,Arity))),
  790	split_args(Mode,Mode,Input,Output,Constants),
  791	(Input = [] -> Call1 = true, Call2 = true;
  792		aleph_delete(Arg/Type,Input,OtherInputs),
  793		Depth1 is Depth - 1,
  794		construct_incall(Lit,Depth1,[Arg/Type],Call1),
  795		construct_call(Lit,Depth,OtherInputs,Call2)),
  796	Call1,
  797	Call2,
  798	aleph_background_predicate(Lit),
  799	get_successes(Lit,NSucc,mode(Mode,Input,Output,Constants)),
  800	fail.
  801gen_layer(_,_).
  802
  803get_successes(Literal,1,M):-
  804	depth_bound_call(Literal), 
  805	update_atoms(Literal,M), !.
  806get_successes(Literal,*,M):-
  807	depth_bound_call(Literal), 
  808	update_atoms(Literal,M).
  809get_successes(Literal,N,M):-
  810	integer(N),
  811	N > 1,
  812	reset_succ,
  813	get_nsuccesses(Literal,N,M).
  814
  815% get at most N matches for a literal
  816get_nsuccesses(Literal,N,M):-
  817	depth_bound_call(Literal), 
  818	retract('$aleph_local'(last_success,Succ0)),
  819	Succ0 < N,
  820	Succ1 is Succ0 + 1,
  821	update_atoms(Literal,M),
  822	asserta('$aleph_local'(last_success,Succ1)),
  823	(Succ1 >= N -> !; true).
  824
  825update_atoms(Atom,M):-
  826	'$aleph_sat_atom'(Atom,M), !.
  827update_atoms(Atom,M):-
  828	assertz('$aleph_sat_atom'(Atom,M)).
  829
  830% call with input term that is an ouput of a previous literal
  831construct_incall(_,_,[],true):- !.
  832construct_incall(not(Lit),Depth,Args,Call):-
  833	!,
  834	construct_incall(Lit,Depth,Args,Call).
  835construct_incall(Lit,Depth,[Pos/Type],Call):-
  836	!,
  837	Call = legal_term(exact,Depth,Type,Term),
  838	tparg(Pos,Lit,Term).
  839construct_incall(Lit,Depth,[Pos/Type|Args],(Call,Calls)):-
  840	tparg(Pos,Lit,Term),
  841	Call = legal_term(exact,Depth,Type,Term),
  842	(var(Depth)-> construct_incall(Lit,_,Args,Calls);
  843		construct_incall(Lit,Depth,Args,Calls)).
  844
  845construct_call(_,_,[],true):- !.
  846construct_call(not(Lit),Depth,Args,Call):-
  847	!,
  848	construct_call(Lit,Depth,Args,Call).
  849construct_call(Lit,Depth,[Pos/Type],Call):-
  850	!,
  851	Call = legal_term(upper,Depth,Type,Term),
  852	tparg(Pos,Lit,Term).
  853construct_call(Lit,Depth,[Pos/Type|Args],(Call,Calls)):-
  854	tparg(Pos,Lit,Term),
  855	Call = legal_term(upper,Depth,Type,Term),
  856	construct_call(Lit,Depth,Args,Calls).
  857
  858% generator of legal terms seen so far
  859legal_term(exact,Depth,Type,Term):-
  860	'$aleph_sat_terms'(TNo,Depth,Term,Type),
  861	once('$aleph_sat_vars'(_,TNo,_,[_|_])).
  862% legal_term(exact,Depth,Type,Term):-
  863	% '$aleph_sat_varscopy'(NewVar,OldVar,Depth),
  864	% once('$aleph_sat_vars'(NewVar,TNo,_,_)),
  865	% '$aleph_sat_terms'(TNo,_,Term,Type),_).
  866legal_term(upper,Depth,Type,Term):-
  867	'$aleph_sat_terms'(TNo,Depth1,Term,Type),
  868	Depth1 \= unknown,
  869	Depth1 < Depth,
  870	once('$aleph_sat_vars'(_,TNo,_,[_|_])).
  871% legal_term(upper,Depth,Type,Term):-
  872	% '$aleph_sat_varscopy'(NewVar,OldVar,Depth),
  873	% once('$aleph_sat_vars'(NewVar,TNo,_,_)),
  874	% '$aleph_sat_terms'(TNo,Depth1,Term,Type),
  875	% Depth1 \= unknown.
  876
  877%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  878% V A R I A B L E  -- S P L I T T I N G
  879
  880
  881split_vars(Depth,FAtom,I,O,C,SplitAtom,IVars,OVars,Equivs):-
  882	setting(splitvars,true), !,
  883        get_args(FAtom,I,[],IVarList),
  884        get_args(FAtom,O,[],OVarList),
  885	get_var_equivs(Depth,IVarList,OVarList,IVars,OVars0,Equivs0),
  886	(Equivs0 = [] ->
  887		OVars = OVars0, SplitAtom = FAtom, Equivs = Equivs0;
  888		functor(FAtom,Name,Arity),
  889		functor(SplitAtom,Name,Arity),
  890		copy_args(FAtom,SplitAtom,I),
  891		copy_args(FAtom,SplitAtom,C),
  892		rename_ovars(O,Depth,FAtom,SplitAtom,Equivs0,Equivs),
  893		get_argterms(SplitAtom,O,[],OVars)).
  894	% write('splitting: '), write(FAtom), write(' to: '), write(SplitAtom), nl.
  895split_vars(_,FAtom,I,O,_,FAtom,IVars,OVars,[]):-
  896	get_vars(FAtom,I,IVars),
  897	get_vars(FAtom,O,OVars).
  898
  899% get equivalent classes of variables from co-references 
  900get_var_equivs(Depth,IVarList,OVarList,IVars,OVars,Equivs):-
  901	sort(IVarList,IVars),
  902	sort(OVarList,OVars),
  903	(Depth = 0 ->
  904		intersect1(IVars,OVarList,IOCoRefs,_),
  905		get_repeats(IVarList,IOCoRefs,ICoRefs);
  906		intersect1(IVars,OVarList,ICoRefs,_)),
  907	get_repeats(OVarList,ICoRefs,CoRefs),
  908	add_equivalences(CoRefs,Depth,Equivs).
  909
  910add_equivalences([],_,[]).
  911add_equivalences([Var|Vars],Depth,[Var/E|Rest]):-
  912	% (Depth = 0 -> E = []; E = [Var]),
  913	E = [Var],
  914	add_equivalences(Vars,Depth,Rest).
  915
  916
  917get_repeats([],L,L).
  918get_repeats([Var|Vars],Ref1,L):-
  919	aleph_member1(Var,Vars), !,
  920	update(Ref1,Var,Ref2),
  921	get_repeats(Vars,Ref2,L).
  922get_repeats([_|Vars],Ref,L):-
  923	get_repeats(Vars,Ref,L).
  924
  925% rename all output vars that are co-references
  926% updates vars database and return equivalent class of variables
  927rename_ovars([],_,_,_,L,L).
  928rename_ovars([ArgNo|Args],Depth,Old,New,CoRefs,Equivalences):-
  929	(ArgNo = Pos/_ -> true; Pos = ArgNo),
  930	tparg(Pos,Old,OldVar),
  931	aleph_delete(OldVar/Equiv,CoRefs,Rest), !,
  932	copy_var(OldVar,NewVar,Depth),
  933	tparg(Pos,New,NewVar),
  934	rename_ovars(Args,Depth,Old,New,[OldVar/[NewVar|Equiv]|Rest],Equivalences).
  935rename_ovars([ArgNo|Args],Depth,Old,New,CoRefs,Equivalences):-
  936	(ArgNo = Pos/_ -> true; Pos = ArgNo),
  937	tparg(Pos,Old,OldVar),
  938	tparg(Pos,New,OldVar),
  939	rename_ovars(Args,Depth,Old,New,CoRefs,Equivalences).
  940
  941% create new  equalities to  allow co-references to re-appear in search
  942insert_eqs([],_,L,L).
  943insert_eqs([OldVar/Equivs|Rest],Depth,Last,NewLast):-
  944	'$aleph_sat_vars'(OldVar,TNo,_,_),
  945	'$aleph_sat_terms'(TNo,_,_,Type),
  946	add_eqs(Equivs,Depth,Type,Last,Last1),
  947	insert_eqs(Rest,Depth,Last1,NewLast).
  948
  949add_eqs([],_,_,L,L).
  950add_eqs([V1|Rest],Depth,Type,Last,NewLast):-
  951	add_eqs(Rest,Depth,V1,Type,Last,Last1),
  952	add_eqs(Rest,Depth,Type,Last1,NewLast).
  953
  954add_eqs([],_,_,_,L,L).
  955add_eqs([Var2|Rest],Depth,Var1,Type,Last,NewLast):-
  956	(Depth = 0 -> 
  957		add_lit(Last,false,(Var1=Var2),[1/Type],[2/Type],[Var1],[Var2],Last1);
  958		add_lit(Last,false,(Var1=Var2),[1/Type,2/Type],[],[Var1,Var2],[],Last1)),
  959	add_eqs(Rest,Depth,Var1,Type,Last1,NewLast).
  960	
  961
  962
  963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  964% utilities for updating mappings between terms and variables
  965
  966% integrate terms specified by a list of arguments
  967% integrating a term means:
  968%	updating 2 databases: terms and vars
  969%	terms contains the term along with a term-id
  970%	vars contains a var-id <-> term-id mapping
  971% var and term-ids are integers
  972integrate_args(_,_,[]).
  973integrate_args(Depth,Literal,[Pos/Type|T]):-
  974        tparg(Pos,Literal,Term),
  975        integrate_term(Depth,Term/Type),
  976	(retract('$aleph_sat_terms'(TNo,Depth,Term,unknown)) ->
  977		asserta('$aleph_sat_terms'(TNo,Depth,Term,Type));
  978		true),
  979        integrate_args(Depth,Literal,T).
  980
  981
  982% integrate a term
  983integrate_term(Depth,Term/Type):-
  984        '$aleph_sat_terms'(TNo,Depth,Term,Type),
  985        '$aleph_sat_vars'(_,TNo,_,[_|_]), !.
  986integrate_term(Depth,Term/Type):-
  987        '$aleph_sat_terms'(TNo,Depth1,Term,Type),
  988        (Type = unknown ; '$aleph_sat_vars'(_,TNo,_,[])), !,
  989	(Depth1 = unknown ->
  990        	retract('$aleph_sat_terms'(TNo,Depth1,Term,Type)),
  991		asserta('$aleph_sat_terms'(TNo,Depth,Term,Type));
  992		true).
  993integrate_term(_,Term/Type):-
  994        '$aleph_sat_terms'(_,_,Term,Type),
  995        Type \= unknown,
  996        !.
  997integrate_term(Depth,Term/Type):-
  998	retract('$aleph_sat'(lastterm,Num)),
  999	retract('$aleph_sat'(lastvar,Var0)),
 1000	TNo is Num + 1,
 1001	Var is Var0 + 1,
 1002	asserta('$aleph_sat'(lastterm,TNo)),
 1003	asserta('$aleph_sat'(lastvar,Var)),
 1004	asserta('$aleph_sat_vars'(Var,TNo,[],[])),
 1005	asserta('$aleph_sat_terms'(TNo,Depth,Term,Type)).
 1006
 1007
 1008%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 1009
 1010% split_args(+Lit,?Mode,-Input,-Output,-Constants)
 1011%       return term-places and types of +,-, and # args in Lit
 1012%       by finding a matching mode declaration if Mode is given
 1013%       otherwise first mode that matches is used
 1014split_args(Lit,Mode,Input,Output,Constants):-
 1015        functor(Lit,Psym,Arity),
 1016	find_mode(mode,Psym/Arity,Mode),
 1017        functor(Template,Psym,Arity),
 1018	copy_modeterms(Mode,Template,Arity),
 1019	Template = Lit,
 1020	tp(Mode,TPList),
 1021	split_tp(TPList,Input,Output,Constants).
 1022
 1023% split_tp(+TPList,-Input,-Output,-Constants)
 1024%	split term-place/type list into +,-,#
 1025split_tp([],[],[],[]).
 1026split_tp([(+Type)/Place|TP],[Place/Type|Input],Output,Constants):-
 1027	!,
 1028	split_tp(TP,Input,Output,Constants).
 1029split_tp([(-Type)/Place|TP],Input,[Place/Type|Output],Constants):-
 1030	!,
 1031	split_tp(TP,Input,Output,Constants).
 1032split_tp([(#Type)/Place|TP],Input,Output,[Place/Type|Constants]):-
 1033	!,
 1034	split_tp(TP,Input,Output,Constants).
 1035split_tp([_|TP],Input,Output,Constants):-
 1036	split_tp(TP,Input,Output,Constants).
 1037
 1038% tp(+Literal,-TPList)
 1039%	return terms and places in Literal
 1040tp(Literal,TPList):-
 1041	functor(Literal,_,Arity),
 1042	tp_list(Literal,Arity,[],[],TPList).
 1043
 1044tp_list(_,0,_,L,L):- !.
 1045tp_list(Term,Pos,PlaceList,TpSoFar,TpList):-
 1046	arg(Pos,Term,Arg),
 1047	aleph_append([Pos],PlaceList,Places),
 1048	unwrap_term(Arg,Places,[Arg/Places|TpSoFar],L1),
 1049	Pos1 is Pos - 1,
 1050	tp_list(Term,Pos1,PlaceList,L1,TpList).
 1051
 1052unwrap_term(Term,_,L,L):-
 1053	var(Term), !.
 1054unwrap_term(Term,Place,TpSoFar,TpList):-
 1055	functor(Term,_,Arity),
 1056	tp_list(Term,Arity,Place,TpSoFar,TpList).
 1057
 1058get_determs(PSym/Arity,L):-
 1059	findall(Pred,'$aleph_global'(determination,determination(PSym/Arity,Pred)),L).
 1060
 1061get_modes(PSym/Arity,L):-
 1062	functor(Lit,PSym,Arity),
 1063	findall(Lit,'$aleph_global'(mode,mode(_,Lit)),L).
 1064
 1065
 1066%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 1067% S E A R C H
 1068
 1069% basic search engine for single clause search
 1070search(S,Nodes):-
 1071	arg(36,S,Time),
 1072	Inf is inf,
 1073	Time =\= Inf, 
 1074	SearchTime is integer(Time),
 1075	SearchTime > 0, !,
 1076	catch(time_bound_call(SearchTime,searchlimit,graphsearch(S,_)),
 1077		searchlimit,p_message('Time limit reached')),
 1078	'$aleph_search'(current,current(_,Nodes,_)).
 1079search(S,Nodes):-
 1080	graphsearch(S,Nodes).
 1081
 1082% basic search engine for theory-based search
 1083tsearch(S,Nodes):-
 1084        arg(36,S,Time),
 1085	Inf is inf,
 1086        Time =\= Inf,
 1087        SearchTime is integer(Time),
 1088        SearchTime > 0, !,
 1089	alarm(SearchTime,throw(searchlimit),Id),
 1090        catch(theorysearch(S,Nodes),searchlimit,p_message('Time limit reached')),
 1091	remove_alarm(Id).
 1092tsearch(S,Nodes):-
 1093        theorysearch(S,Nodes).
 1094
 1095graphsearch(S,Nodes):-
 1096	next_node(_), !,
 1097        arg(3,S,RefineOp),
 1098	arg(23,S,LazyPreds),
 1099        repeat,
 1100	next_node(NodeRef),
 1101        once(retract('$aleph_search'(current,current(LastE,Last,BestSoFar)))),
 1102        expand(RefineOp,S,NodeRef,Node,Path,MinLength,Succ,PosCover,NegCover,OVars,
 1103		PrefixClause,PrefixTV,PrefixLength),
 1104        ((LazyPreds = []; RefineOp \= false)  -> Succ1 = Succ;
 1105		lazy_evaluate(Succ,LazyPreds,Path,PosCover,NegCover,Succ1)),
 1106	NextE is LastE + 1,
 1107        get_gains(S,Last,BestSoFar,Path,PrefixClause,PrefixTV,PrefixLength,
 1108                MinLength,Succ1,PosCover,NegCover,OVars,NextE,Last0,NextBest0),
 1109	(RefineOp = false ->
 1110        	get_sibgains(S,Node,Last0,NextBest0,Path,PrefixClause,
 1111			PrefixTV,PrefixLength,MinLength,PosCover,NegCover,
 1112			OVars,NextE,Last1,NextBest);
 1113		Last1 = Last0, NextBest = NextBest0),
 1114        asserta('$aleph_search'(current,current(NextE,Last1,NextBest))),
 1115        NextL is Last + 1,
 1116        asserta('$aleph_search_expansion'(NextE,Node,NextL,Last1)),
 1117        (discontinue_search(S,NextBest,Last1) ->
 1118                '$aleph_search'(current,current(_,Nodes,_));
 1119                prune_open(S,BestSoFar,NextBest),
 1120                get_nextbest(S,Next),
 1121		Next = none,
 1122		'$aleph_search'(current,current(_,Nodes,_))),
 1123	!.
 1124graphsearch(_,Nodes):-
 1125	'$aleph_search'(current,current(_,Nodes,_)).
 1126
 1127theorysearch(S,Nodes):-
 1128        next_node(_), !,
 1129        '$aleph_global'(atoms,atoms(pos,Pos)),
 1130        '$aleph_global'(atoms,atoms(neg,Neg)),
 1131        interval_count(Pos,P),
 1132        interval_count(Neg,N),
 1133        repeat,
 1134        next_node(NodeRef),
 1135	'$aleph_search_node'(NodeRef,Theory,_,_,_,_,_,_),
 1136        once(retract('$aleph_search'(current,current(_,Last,BestSoFar)))),
 1137        get_theory_gain(S,Last,BestSoFar,Theory,Pos,Neg,P,N,NextBest,Last1),
 1138        asserta('$aleph_search'(current,current(0,Last1,NextBest))),
 1139        (discontinue_search(S,NextBest,Last1) ->
 1140                '$aleph_search'(current,current(_,Nodes,_));
 1141                prune_open(S,BestSoFar,NextBest),
 1142                get_nextbest(S,Next),
 1143                Next = none,
 1144                '$aleph_search'(current,current(_,Nodes,_))),
 1145	 !.
 1146theorysearch(_,Nodes):-
 1147        '$aleph_search'(current,current(_,Nodes,_)).
 1148
 1149next_node(NodeRef):-
 1150	once('$aleph_search'(nextnode,NodeRef)), !.
 1151
 1152get_search_settings(S):-
 1153        functor(S,set,47),
 1154	setting(nodes,MaxNodes), arg(1,S,MaxNodes),
 1155	setting(explore,Explore), arg(2,S,Explore),
 1156	setting(refineop,RefineOp), arg(3,S,RefineOp),
 1157	setting(searchstrat,SearchStrat), setting(evalfn,EvalFn),
 1158	arg(4,S,SearchStrat/EvalFn),
 1159	(setting(greedy,Greedy)-> arg(5,S,Greedy); arg(5,S,false)),
 1160	setting(verbosity,Verbose), arg(6,S,Verbose),
 1161	setting(clauselength,CLength), arg(7,S,CLength),
 1162	setting(caching,Cache), arg(8,S,Cache),
 1163	(setting(prune_defs,Prune)-> arg(9,S,Prune); arg(9,S,false)),
 1164	setting(lazy_on_cost,LCost), arg(10,S,LCost),
 1165	setting(lazy_on_contradiction,LContra), arg(11,S,LContra),
 1166	setting(lazy_negs,LNegs), arg(12,S,LNegs),
 1167	setting(minpos,MinPos), arg(13,S,MinPos),
 1168	setting(depth,Depth), arg(14,S,Depth),
 1169	setting(cache_clauselength,CCLim), arg(15,S,CCLim),
 1170        ('$aleph_global'(size,size(pos,PSize))-> arg(16,S,PSize); arg(16,S,0)),
 1171	setting(noise,Noise), arg(17,S,Noise),
 1172	setting(minacc,MinAcc), arg(18,S,MinAcc),
 1173	setting(minscore,MinScore), arg(19,S,MinScore),
 1174        ('$aleph_global'(size,size(rand,RSize))-> arg(20,S,RSize); arg(20,S,0)),
 1175	setting(mingain,MinGain), arg(21,S,MinGain),
 1176	setting(search,Search), arg(22,S,Search),
 1177	findall(PN/PA,'$aleph_global'(lazy_evaluate,lazy_evaluate(PN/PA)),LazyPreds),
 1178	arg(23,S,LazyPreds),
 1179        ('$aleph_global'(size,size(neg,NSize))-> arg(24,S,NSize); arg(24,S,0)),
 1180	setting(openlist,OSize), arg(25,S,OSize),
 1181        setting(check_redundant,RCheck), arg(26,S,RCheck),
 1182        ('$aleph_sat'(eq,Eq) -> arg(27,S,Eq); arg(27,S,false)),
 1183        ('$aleph_sat'(hovars,HOVars) -> arg(28,S,HOVars); arg(28,S,_HOVars)),
 1184	setting(prooftime,PTime), arg(29,S,PTime),
 1185	setting(construct_bottom,CBott), arg(30,S,CBott),
 1186	(get_ovars1(false,1,HIVars) ->  arg(31,S,HIVars); arg(31,S,[])),
 1187	setting(language,Lang), arg(32,S,Lang),
 1188	setting(splitvars,Split), arg(33,S,Split),
 1189	setting(proof_strategy,Proof), arg(34,S,Proof),
 1190	setting(portray_search,VSearch), arg(35,S,VSearch),
 1191	setting(searchtime,Time), arg(36,S,Time),
 1192	setting(optimise_clauses,Optim), arg(37,S,Optim),
 1193	setting(newvars,NewV), arg(38,S,NewV),
 1194	(setting(rls_type,RlsType) -> arg(39,S,RlsType);arg(39,S,false)),
 1195	setting(minposfrac,MinPosFrac), arg(40,S,MinPosFrac),
 1196	(setting(recursion,_Recursion) -> true; _Recursion = false),
 1197	prolog_type(Prolog), arg(41,S,Prolog),
 1198	setting(interactive,Interactive), arg(42,S,Interactive),
 1199	setting(lookahead,LookAhead), arg(43,S,LookAhead),
 1200	(setting(construct_features,Features)-> arg(44,S,Features); arg(44,S,false)),
 1201	setting(max_features,FMax), arg(45,S,FMax),
 1202	setting(subsample,SS), arg(46,S,SS),
 1203	setting(subsamplesize,SSize), arg(47,S,SSize).
 1204
 1205% stop search from proceeding if certain
 1206% conditions are reached. These are:
 1207%	. minacc and minpos values reached in rrr search
 1208%	. best hypothesis has accuracy 1.0 if evalfn=accuracy
 1209%	. best hypothesis covers all positive examples
 1210discontinue_search(S,[P,_,_,F|_]/_,_):-
 1211	arg(39,S,RlsType),
 1212	RlsType = rrr, 
 1213	arg(13,S,MinPos),
 1214	P >= MinPos,
 1215	arg(19,S,MinScore),
 1216	F >= MinScore, !.
 1217discontinue_search(S,_,Nodes):-
 1218        arg(1,S,MaxNodes),
 1219        Nodes >= MaxNodes, !,
 1220	p_message('node limit reached').
 1221discontinue_search(S,_,_):-
 1222        arg(44,S,Features),
 1223	Features = true,
 1224	arg(45,S,FMax),
 1225	'$aleph_search'(last_good,LastGood),
 1226        LastGood >= FMax, !,
 1227	p_message('feature limit reached').
 1228discontinue_search(S,[_,_,_,F|_]/_,_):-
 1229        arg(4,S,_/Evalfn),
 1230	Evalfn = accuracy,
 1231	F = 1.0, !.
 1232discontinue_search(S,Best,_):-
 1233	arg(2,S,Explore),
 1234	Explore = false,
 1235        arg(4,S,_/Evalfn),
 1236	Evalfn \= user,
 1237	Evalfn \= posonly,
 1238	arg(22,S,Search),
 1239	Search \= ic,
 1240	Best = [P|_]/_,
 1241	arg(16,S,P).
 1242
 1243update_max_head_count(N,0):-
 1244	retractall('$aleph_local'(max_head_count,_)),
 1245	asserta('$aleph_local'(max_head_count,N)), !.
 1246update_max_head_count(Count,Last):-
 1247	'$aleph_search_node'(Last,LitNum,_,_,PosCover,_,_,_), !,
 1248	asserta('$aleph_local'(head_lit,LitNum)),
 1249	interval_count(PosCover,N),
 1250	Next is Last - 1,
 1251	(N > Count -> update_max_head_count(N,Next);
 1252		update_max_head_count(Count,Next)).
 1253update_max_head_count(Count,Last):-
 1254	Next is Last - 1,
 1255	update_max_head_count(Count,Next).
 1256
 1257expand(false,S,NodeRef,NodeRef,Path1,Length,Descendents,PosCover,NegCover,OVars,C,TV,CL):-
 1258	!,
 1259        '$aleph_search_node'(NodeRef,LitNum,Path,Length/_,PCover,NCover,OVars,_),
 1260	arg(46,S,SSample),
 1261	(SSample = false -> PosCover = PCover, NegCover = NCover;
 1262		get_sample_cover(S,PosCover,NegCover)),
 1263        aleph_append([LitNum],Path,Path1),
 1264	get_pclause(Path1,[],C,TV,CL,_),
 1265        '$aleph_sat_litinfo'(LitNum,_,_,_,_,Dependents),
 1266        intersect1(Dependents,Path1,_,Succ),
 1267        check_parents(Succ,OVars,Descendents,_).
 1268expand(_,S,NodeRef,NodeRef,Path1,Length,[_],PosCover,NegCover,OVars,_,_,_):-
 1269        retract('$aleph_search_node'(NodeRef,_,Path1,Length/_,_,_,OVars,_)),
 1270	get_sample_cover(S,PosCover,NegCover).
 1271
 1272get_sample_cover(S,PosCover,NegCover):-
 1273        arg(5,S,Greedy),
 1274        (Greedy = true ->
 1275                '$aleph_global'(atoms_left,atoms_left(pos,PCover));
 1276                arg(16,S,PSize),
 1277                PCover = [1-PSize]),
 1278        arg(4,S,_/Evalfn),
 1279	(Evalfn = posonly -> 
 1280                '$aleph_global'(atoms_left,atoms_left(rand,NCover));
 1281                arg(24,S,NSize),
 1282                NCover = [1-NSize]),
 1283	arg(46,S,SSample),
 1284	(SSample = false -> PosCover = PCover, NegCover = NCover;
 1285		arg(47,S,SampleSize),
 1286		interval_sample(SampleSize,PCover,PosCover),
 1287		interval_sample(SampleSize,NCover,NegCover)).
 1288
 1289get_ovars([],_,V,V).
 1290get_ovars([LitNum|Lits],K,VarsSoFar,Vars):-
 1291	get_ovars1(K,LitNum,OVars),
 1292	aleph_append(VarsSoFar,OVars,Vars1),
 1293	get_ovars(Lits,K,Vars1,Vars).
 1294
 1295get_ovars1(false,LitNum,OVars):-
 1296	'$aleph_sat_ovars'(LitNum,OVars), !.
 1297get_ovars1(false,LitNum,OVars):-
 1298	!,
 1299	'$aleph_sat_litinfo'(LitNum,_,Atom,_,O,_),
 1300	get_vars(Atom,O,OVars).
 1301get_ovars1(K,LitNum,OVars):-
 1302	'$aleph_sat_ovars'(LitNum,K,OVars), !.
 1303get_ovars1(K,LitNum,OVars):-
 1304	'$aleph_sat_litinfo'(LitNum,K,_,Atom,_,O,_),
 1305	get_vars(Atom,O,OVars).
 1306
 1307% get set of vars at term-places specified
 1308get_vars(not(Literal),Args,Vars):-
 1309	!,
 1310	get_vars(Literal,Args,Vars).
 1311get_vars(_,[],[]).
 1312get_vars(Literal,[ArgNo|Args],Vars):-
 1313	(ArgNo = Pos/_ -> true; Pos = ArgNo),
 1314	tparg(Pos,Literal,Term),
 1315	get_vars_in_term([Term],TV1),
 1316	get_vars(Literal,Args,TV2),
 1317	update_list(TV2,TV1,Vars).
 1318
 1319get_vars_in_term([],[]).
 1320get_vars_in_term([Var|Terms],[Var|TVars]):-
 1321	integer(Var), !,
 1322	get_vars_in_term(Terms,TVars).
 1323get_vars_in_term([Term|Terms],TVars):-
 1324	Term =.. [_|Terms1],
 1325	get_vars_in_term(Terms1,TV1),
 1326	get_vars_in_term(Terms,TV2),
 1327	update_list(TV2,TV1,TVars).
 1328
 1329% get terms at term-places specified
 1330% need not be variables
 1331get_argterms(not(Literal),Args,TermsSoFar,Terms):-
 1332        !,
 1333        get_argterms(Literal,Args,TermsSoFar,Terms).
 1334get_argterms(_,[],Terms,Terms).
 1335get_argterms(Literal,[ArgNo|Args],TermsSoFar,Terms):-
 1336	(ArgNo = Pos/_ -> true; Pos = ArgNo),
 1337        tparg(Pos,Literal,Term),
 1338        update(TermsSoFar,Term,T1),
 1339        get_argterms(Literal,Args,T1,Terms).
 1340
 1341% get list of terms at arg positions specified
 1342get_args(not(Literal),Args,TermsSoFar,Terms):-
 1343        !,
 1344        get_args(Literal,Args,TermsSoFar,Terms).
 1345get_args(_,[],Terms,Terms).
 1346get_args(Literal,[ArgNo|Args],TermsSoFar,Terms):-
 1347	(ArgNo = Pos/_ -> true; Pos = ArgNo),
 1348        tparg(Pos,Literal,Term),
 1349        get_args(Literal,Args,[Term|TermsSoFar],Terms).
 1350
 1351
 1352get_ivars([],_,V,V).
 1353get_ivars([LitNum|Lits],K,VarsSoFar,Vars):-
 1354	get_ivars1(K,LitNum,IVars),
 1355	aleph_append(VarsSoFar,IVars,Vars1),
 1356	get_ivars(Lits,K,Vars1,Vars).
 1357
 1358get_ivars1(false,LitNum,IVars):-
 1359	'$aleph_sat_ivars'(LitNum,IVars), !.
 1360get_ivars1(false,LitNum,IVars):-
 1361	!,
 1362	'$aleph_sat_litinfo'(LitNum,_,Atom,I,_,_),
 1363	get_vars(Atom,I,IVars).
 1364get_ivars1(K,LitNum,IVars):-
 1365	'$aleph_sat_ivars'(LitNum,K,IVars), !.
 1366get_ivars1(K,LitNum,IVars):-
 1367	'$aleph_sat_litinfo'(LitNum,K,_,Atom,I,_,_),
 1368	get_vars(Atom,I,IVars).
 1369
 1370check_parents([],_,[],[]).
 1371check_parents([LitNum|Lits],OutputVars,[LitNum|DLits],Rest):-
 1372	get_ivars1(false,LitNum,IVars),
 1373	aleph_subset1(IVars,OutputVars), !,
 1374	check_parents(Lits,OutputVars,DLits,Rest).
 1375check_parents([LitNum|Lits],OutputVars,DLits,[LitNum|Rest]):-
 1376	check_parents(Lits,OutputVars,DLits,Rest), !.
 1377
 1378get_gains(S,Last,Best,_,_,_,_,_,_,_,_,_,_,Last,Best):-
 1379        discontinue_search(S,Best,Last), !.
 1380get_gains(_,Last,Best,_,_,_,_,_,[],_,_,_,_,Last,Best):- !.
 1381get_gains(S,Last,Best,Path,C,TV,L,Min,[L1|Succ],Pos,Neg,OVars,E,Last1,NextBest):-
 1382        get_gain(S,upper,Last,Best,Path,C,TV,L,Min,L1,Pos,Neg,OVars,E,Best1,Node1), !,
 1383        get_gains(S,Node1,Best1,Path,C,TV,L,Min,Succ,Pos,Neg,OVars,E,Last1,NextBest).
 1384get_gains(S,Last,BestSoFar,Path,C,TV,L,Min,[_|Succ],Pos,Neg,OVars,E,Last1,NextBest):-
 1385        get_gains(S,Last,BestSoFar,Path,C,TV,L,Min,Succ,Pos,Neg,OVars,E,Last1,NextBest),
 1386        !.
 1387
 1388get_sibgains(S,Node,Last,Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,Last1,NextBest):-
 1389        '$aleph_search_node'(Node,LitNum,_,_,_,_,_,OldE),
 1390        '$aleph_search_expansion'(OldE,_,_,LastSib),
 1391        '$aleph_sat_litinfo'(LitNum,_,_,_,_,Desc),
 1392        Node1 is Node + 1,
 1393        arg(31,S,HIVars),
 1394        aleph_delete_list(HIVars,OVars,LVars),
 1395        get_sibgain(S,LVars,LitNum,Desc,Node1,LastSib,Last,
 1396                Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,NextBest,Last1), !.
 1397
 1398get_sibgain(S,_,_,_,Node,Node1,Last,Best,_,_,_,_,_,_,_,_,_,Best,Last):-
 1399        (Node > Node1;
 1400        discontinue_search(S,Best,Last)), !.
 1401get_sibgain(S,LVars,LitNum,Desc,Node,LastSib,Last,Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,LBest,LNode):-
 1402        arg(23,S,Lazy),
 1403        get_sibpncover(Lazy,Node,Desc,Pos,Neg,Sib1,PC,NC),
 1404        lazy_evaluate([Sib1],Lazy,Path,PC,NC,[Sib]),
 1405        get_ivars1(false,Sib,SibIVars),
 1406        (intersects(SibIVars,LVars) -> Flag = upper;
 1407                get_ovars1(false,Sib,SibOVars),
 1408                (intersects(SibOVars,LVars) -> Flag = upper; Flag = exact)),
 1409        get_gain(S,Flag,Last,Best,Path,C,TV,L,Min,Sib,PC,NC,OVars,E,Best1,Node1), !,
 1410        NextNode is Node + 1,
 1411        get_sibgain(S,LVars,LitNum,Desc,NextNode,LastSib,Node1,Best1,Path,C,TV,L,
 1412                        Min,Pos,Neg,OVars,E,LBest,LNode), !.
 1413get_sibgain(S,LVars,LitNum,Desc,Node,LastSib,Last,Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,Best1,Node1):-
 1414	NextNode is Node + 1,
 1415        get_sibgain(S,LVars,LitNum,Desc,NextNode,LastSib,Last,Best,Path,C,TV,L,
 1416                        Min,Pos,Neg,OVars,E,Best1,Node1), !.
 1417
 1418
 1419get_sibgain(S,LVars,LitNum,Node,LastSib,Last,Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,Best1,Node1):-
 1420	NextNode is Node + 1,
 1421	get_sibgain(S,LVars,LitNum,NextNode,LastSib,Last,Best,Path,C,TV,L,Min,Pos,Neg,
 1422			OVars,E,Best1,Node1), !.
 1423
 1424get_sibpncover(Lazy,NodeNum,Desc,Pos,Neg,Sib,PC,NC):-
 1425        '$aleph_search_node'(NodeNum,Sib,_,_,Pos1,Neg1,_,_),
 1426        '$aleph_sat_litinfo'(Sib,_,Atom,_,_,_),
 1427        \+(aleph_member1(Sib,Desc)),
 1428        functor(Atom,Name,Arity),
 1429        (aleph_member1(Name/Arity,Lazy) ->
 1430                PC = Pos, NC = Neg;
 1431                calc_intersection(Pos,Pos1,PC),
 1432                calc_intersection(Neg,Neg1,NC)).
 1433
 1434% in some cases, it is possible to simply use the intersection of
 1435% covers cached. The conditions under which this is possible was developed
 1436% in discussions with James Cussens
 1437calc_intersection(A1/[B1-L1],A2/[B2-L2],A/[B-L]):-
 1438	!,
 1439	intervals_intersection(A1,A2,A),
 1440	B3 is max(B1,B2),
 1441	(intervals_intersects(A1,[B2-L2],X3-_) -> true; X3 = B3),
 1442	(intervals_intersects(A2,[B1-L1],X4-_) -> true; X4 = B3),
 1443	B4 is min(X3,B3),
 1444	B is min(X4,B4),
 1445	L is max(L1,L2).
 1446calc_intersection(A1/_,A2,A):-
 1447	!,
 1448	intervals_intersection(A1,A2,A).
 1449calc_intersection(A1,A2/_,A):-
 1450	!,
 1451	intervals_intersection(A1,A2,A).
 1452calc_intersection(A1,A2,A):-
 1453	intervals_intersection(A1,A2,A).
 1454
 1455get_gain(S,_,Last,Best,Path,_,_,_,MinLength,_,Pos,Neg,OVars,E,Best1,NewLast):-
 1456        arg(3,S,RefineOp),
 1457        RefineOp \= false , !,
 1458	get_refine_gain(S,Last,Best,Path,MinLength,Pos,Neg,OVars,E,Best1,NewLast).
 1459get_gain(S,Flag,Last,Best/Node,Path,C,TV,Len1,MinLen,L1,Pos,Neg,OVars,E,Best1,Last1):-
 1460	arg(26,S,RCheck),
 1461	arg(33,S,SplitVars),
 1462	retractall('$aleph_search'(covers,_)),
 1463	retractall('$aleph_search'(coversn,_)),
 1464        get_pclause([L1],TV,Lit1,_,Len2,LastD),
 1465	split_ok(SplitVars,C,Lit1), !,
 1466        extend_clause(C,Lit1,Clause),
 1467	(RCheck = true ->
 1468		(redundant(Clause,Lit1) -> fail; true);
 1469		true),
 1470        CLen is Len1 + Len2,
 1471        length_ok(S,MinLen,CLen,LastD,EMin,ELength),
 1472	% arg(41,S,Prolog),
 1473        split_clause(Clause,Head,Body),
 1474        % (Prolog = yap ->
 1475		% assertz('$aleph_search'(pclause,pclause(Head,Body)),DbRef);
 1476		% assertz('$aleph_search'(pclause,pclause(Head,Body)))),
 1477	assertz('$aleph_search'(pclause,pclause(Head,Body))),
 1478        arg(6,S,Verbosity),
 1479        (Verbosity >= 1 ->
 1480		pp_dclause(Clause);
 1481	true),
 1482        get_gain1(S,Flag,Clause,CLen,EMin/ELength,Last,Best/Node,
 1483                        Path,L1,Pos,Neg,OVars,E,Best1),
 1484        % (Prolog = yap ->
 1485		% erase(DbRef);
 1486		% retractall('$aleph_search'(pclause,_))),
 1487	retractall('$aleph_search'(pclause,_)),
 1488        Last1 is Last + 1.
 1489get_gain(_,_,Last,Best,_,_,_,_,_,_,_,_,_,_,Best,Last).
 1490
 1491get_refine_gain(S,Last,Best/Node,Path,MinLength,Pos,Neg,OVars,E,Best1,NewLast):-
 1492        arg(3,S,RefineOp),
 1493	RefineOp = rls,
 1494	refine_prelims(Best/Node,Last),
 1495	rls_refine(clauses,Path,Path1),
 1496	get_refine_gain1(S,Path1,MinLength,Pos,Neg,OVars,E,Best1,NewLast),
 1497	!.
 1498get_refine_gain(S,Last,Best/Node,Path,MinLength,Pos,Neg,OVars,E,Best1,NewLast):-
 1499        arg(3,S,RefineOp),
 1500	RefineOp \= rls,
 1501	refine_prelims(Best/Node,Last),
 1502	Path = CL-[Example,Type,_,Clause],
 1503	arg(30,S,ConstructBottom),
 1504        arg(43,S,LookAhead),
 1505        get_user_refinement(RefineOp,LookAhead,Clause,R,_),
 1506	match_bot(ConstructBottom,R,R1,LitNums),
 1507	Path1 = CL-[Example,Type,LitNums,R1],
 1508	get_refine_gain1(S,Path1,MinLength,Pos,Neg,OVars,E,Best1,NewLast),
 1509	!.
 1510get_refine_gain(_,_,_,_,_,_,_,_,_,Best,Last):-
 1511	retract('$aleph_search'(best_refinement,best_refinement(Best))),
 1512	retract('$aleph_search'(last_refinement,last_refinement(Last))).
 1513
 1514get_theory_gain(S,Last,BestSoFar,T0,Pos,Neg,P,N,Best1,NewLast):-
 1515	refine_prelims(BestSoFar,Last),
 1516	arg(3,S,RefineOp),
 1517	(RefineOp = rls -> rls_refine(theories,T0,T1); fail),
 1518	arg(23,S,LazyPreds),
 1519	(LazyPreds = [] -> Theory = T1;
 1520		lazy_evaluate_theory(T1,LazyPreds,Pos,Neg,Theory)),
 1521	retract('$aleph_search'(best_refinement,best_refinement(OldBest))),
 1522	retract('$aleph_search'(last_refinement,last_refinement(OldLast))),
 1523        arg(6,S,Verbosity),
 1524        (Verbosity >= 1 ->
 1525                p_message('new refinement'),
 1526                pp_dclauses(Theory);
 1527        true),
 1528	record_pclauses(Theory),
 1529	get_theory_gain1(S,Theory,OldLast,OldBest,Pos,Neg,P,N,Best1),
 1530	retractall('$aleph_search'(pclause,_)),
 1531        NewLast is OldLast + 1,
 1532	asserta('$aleph_search'(last_refinement,last_refinement(NewLast))),
 1533        asserta('$aleph_search'(best_refinement,best_refinement(Best1))),
 1534	(discontinue_search(S,Best1,NewLast) ->
 1535		retract('$aleph_search'(last_refinement,last_refinement(_))),
 1536		retract('$aleph_search'(best_refinement,best_refinement(_)));
 1537		fail),
 1538	!.
 1539get_theory_gain(_,_,_,_,_,_,_,_,Best,Last):-
 1540	'$aleph_search'(best_refinement,best_refinement(Best)),
 1541	'$aleph_search'(last_refinement,last_refinement(Last)).
 1542
 1543refine_prelims(Best,Last):-
 1544	retractall('$aleph_search'(last_refinement,_)),
 1545	retractall('$aleph_search'(best_refinement,_)),
 1546        asserta('$aleph_search'(best_refinement,best_refinement(Best))),
 1547	asserta('$aleph_search'(last_refinement,last_refinement(Last))).
 1548
 1549get_refine_gain1(S,Path,MinLength,Pos,Neg,OVars,E,Best1,NewLast):-
 1550        arg(23,S,LazyPreds),
 1551	Path = CL-[Example,Type,Ids,Refine],
 1552	(LazyPreds = [] -> Ids1 = Ids, Clause = Refine;
 1553		lazy_evaluate_refinement(Ids,Refine,LazyPreds,Pos,Neg,Ids1,Clause)),
 1554	retractall('$aleph_search'(covers,_)),
 1555	retractall('$aleph_search'(coversn,_)),
 1556	Path1 = CL-[Example,Type,Ids1,Clause],
 1557	split_clause(Clause,Head,Body),
 1558	nlits(Body,CLength0),
 1559	CLength is CLength0 + 1,
 1560	length_ok(S,MinLength,CLength,0,EMin,ELength),
 1561	arg(41,S,Prolog),
 1562	split_clause(Clause,Head,Body),
 1563	(Prolog = yap ->
 1564		assertz('$aleph_search'(pclause,pclause(Head,Body)),DbRef);
 1565		assertz('$aleph_search'(pclause,pclause(Head,Body)))),
 1566	retract('$aleph_search'(best_refinement,best_refinement(OldBest))),
 1567	retract('$aleph_search'(last_refinement,last_refinement(OldLast))),
 1568        arg(6,S,Verbosity),
 1569        (Verbosity >= 1 ->
 1570		p_message('new refinement'),
 1571		pp_dclause(Clause);
 1572	true),
 1573	once(get_gain1(S,upper,Clause,CLength,EMin/ELength,OldLast,OldBest,
 1574		Path1,[],Pos,Neg,OVars,E,Best1)),
 1575	(Prolog = yap ->
 1576		erase(DbRef);
 1577		retractall('$aleph_search'(pclause,_))),
 1578	NewLast is OldLast + 1,
 1579	asserta('$aleph_search'(last_refinement,last_refinement(NewLast))),
 1580        asserta('$aleph_search'(best_refinement,best_refinement(Best1))),
 1581	(discontinue_search(S,Best1,NewLast) ->
 1582		retract('$aleph_search'(last_refinement,last_refinement(_))),
 1583		retract('$aleph_search'(best_refinement,best_refinement(_)));
 1584		fail),
 1585	!.
 1586
 1587get_theory_gain1(S,Theory,Last,Best,Pos,Neg,P,N,Best1):-
 1588        (false -> p_message('constraint violated'),
 1589                Contradiction = true;
 1590                Contradiction = false),
 1591	Contradiction = false,
 1592        Node1 is Last + 1,
 1593	arg(32,S,Lang),
 1594	theory_lang_ok(Theory,Lang),
 1595	arg(38,S,NewVars),
 1596	theory_newvars_ok(Theory,NewVars),
 1597	arg(14,S,Depth),
 1598	arg(29,S,Time),
 1599	arg(34,S,Proof),
 1600        prove(Depth/Time/Proof,pos,(X:-X),Pos,PCvr,TP),
 1601        prove(Depth/Time/Proof,neg,(X:-X),Neg,NCvr,FP),
 1602	arg(4,S,_/Evalfn),
 1603	Correct is TP + (N - FP),
 1604	Incorrect is FP + (P - TP),
 1605	length(Theory,L),
 1606	Label = [Correct,Incorrect,L],
 1607	complete_label(Evalfn,Theory,Label,Label1),
 1608	get_search_keys(heuristic,Label1,SearchKeys),
 1609	arg(6,S,Verbosity),
 1610	(Verbosity >= 1 -> p_message(Correct/Incorrect); true),
 1611	asserta('$aleph_search_node'(Node1,Theory,[],0,PCvr,NCvr,[],0)),
 1612	update_open_list(SearchKeys,Node1,Label1),
 1613	update_best_theory(S,Theory,PCvr,NCvr,Best,Label1/Node1,Best1), !.
 1614get_theory_gain1(_,_,_,Best,_,_,_,_,Best).
 1615
 1616get_gain1(S,_,C,CL,_,Last,Best,Path,_,Pos,Neg,_,E,Best):-
 1617        abandon_branch(S,C), !,
 1618        Node1 is Last + 1,
 1619        arg(3,S,RefineOp),
 1620        arg(7,S,ClauseLength),
 1621	arg(35,S,VSearch),
 1622        (ClauseLength = CL -> true;
 1623                (RefineOp = false  ->
 1624                        asserta('$aleph_search_node'(Node1,0,Path,0,Pos,Neg,[],E));
 1625			true)),
 1626	(VSearch = true ->
 1627		asserta('$aleph_search'(bad,Node1)),
 1628		asserta('$aleph_search_node'(Node1,C));
 1629		true).
 1630get_gain1(S,_,Clause,_,_,_,Best,_,_,_,_,_,_,Best):-
 1631        arg(8,S,Caching),
 1632        Caching = true,
 1633        skolemize(Clause,SHead,SBody,0,_),
 1634        '$aleph_search_prunecache'([SHead|SBody]), !,
 1635	arg(6,S,Verbosity),
 1636        (Verbosity >= 1 -> p_message('in prune cache'); true).
 1637get_gain1(S,Flag,C,CL,EMin/EL,Last,Best/Node,Path,L1,Pos,Neg,OVars,E,Best1):-
 1638	split_clause(C,Head,Body),
 1639	arg(22,S,Search),
 1640        ((Search \== ic, false) -> p_message('constraint violated'),
 1641                Contradiction = true;
 1642                Contradiction = false),
 1643        Node1 is Last + 1,
 1644        arg(8,S,Caching),
 1645        (Caching = true -> arg(15,S,CCLim),
 1646		get_cache_entry(CCLim,C,Entry);
 1647		Entry = false),
 1648	arg(35,S,VSearch),
 1649	(VSearch = true ->
 1650		asserta('$aleph_search_node'(Node1,C));
 1651		true),
 1652        arg(3,S,RefineOp),
 1653	refinement_ok(RefineOp,Entry),
 1654	arg(32,S,Lang),
 1655	lang_ok((Head:-Body),Lang),
 1656	arg(38,S,NewVars),
 1657	newvars_ok((Head:-Body),NewVars),
 1658	arg(34,S,Proof),
 1659	arg(37,S,Optim),
 1660	rewrite_clause(Proof,Optim,(Head:-Body),(Head1:-Body1)),
 1661	(Search = ic ->
 1662		PCvr = [],
 1663		Label = [_,_,CL],
 1664		ccheck(S,(Head1:-Body1),NCvr,Label);
 1665        	prove_examples(S,Flag,Contradiction,Entry,Best,CL,EL,
 1666				(Head1:-Body1),Pos,Neg,PCvr,NCvr,Label)
 1667	),
 1668        arg(4,S,SearchStrat/Evalfn),
 1669	arg(40,S,MinPosFrac),
 1670	((MinPosFrac > 0.0 ; Evalfn = wracc) ->
 1671		reset_clause_prior(S,Head1);
 1672		true
 1673	),
 1674	arg(46,S,SSample),
 1675	(SSample = true ->
 1676		arg(47,S,SampleSize),
 1677		estimate_label(SampleSize,Label,Label0);
 1678		Label0 = Label),
 1679	complete_label(Evalfn,C,Label0,Label1),
 1680	compression_ok(Evalfn,Label1),
 1681        get_search_keys(SearchStrat,Label1,SearchKeys),
 1682        arg(6,S,Verbosity),
 1683	arg(10,S,LCost),
 1684	arg(11,S,LContra),
 1685        ((Verbosity >= 1, LContra = false, LCost = false) ->
 1686		Label = [A,B|_],
 1687		p_message(A/B);
 1688	true),
 1689        arg(7,S,ClauseLength),
 1690	(RefineOp = false ->
 1691		get_ovars1(false,L1,OVars1),
 1692		aleph_append(OVars1,OVars,OVars2);
 1693		true),
 1694        ((ClauseLength=CL, RefineOp = false) -> true;
 1695		(RefineOp = false ->
 1696                	asserta('$aleph_search_node'(Node1,L1,Path,EMin/EL,PCvr,
 1697					NCvr,OVars2,E));
 1698                	asserta('$aleph_search_node'(Node1,0,Path,EMin/EL,PCvr,
 1699					NCvr,[],E))),
 1700                	update_open_list(SearchKeys,Node1,Label1)),
 1701	(VSearch = true ->
 1702		asserta('$aleph_search'(label,label(Node1,Label)));
 1703		true),
 1704        (((RefineOp \= false,Contradiction=false);
 1705		(arg(28,S,HOVars),clause_ok(Contradiction,HOVars,OVars2))) ->
 1706                update_best(S,C,PCvr,NCvr,Best/Node,Label1/Node1,Best1);
 1707                Best1=Best/Node),
 1708	!.
 1709get_gain1(_,_,_,_,_,_,Best,_,_,_,_,_,_,Best).
 1710
 1711
 1712abandon_branch(S,C):-
 1713        arg(9,S,PruneDefined),
 1714        PruneDefined = true,
 1715        prune(C), !,
 1716        arg(6,S,Verbosity),
 1717        (Verbosity >= 1 -> p_message(pruned); true).
 1718
 1719clause_ok(false,V1,V2):-
 1720        aleph_subset1(V1,V2).
 1721
 1722% check to see if a clause is acceptable
 1723% 	unacceptable if it fails noise, minacc, or minpos settings
 1724%	unacceptable if it fails search or language constraints
 1725clause_ok(_,_):-
 1726	false, !, fail.
 1727clause_ok(_,Label):-
 1728	extract_pos(Label,P),
 1729	extract_neg(Label,N),
 1730	Acc is P/(P+N),
 1731	setting(noise,Noise),
 1732	setting(minacc,MinAcc),
 1733	setting(minpos,MinPos),
 1734	(N > Noise; Acc < MinAcc; P < MinPos), !, fail.
 1735clause_ok(Clause,_):-
 1736	prune(Clause), !, fail.
 1737clause_ok(Clause,_):-
 1738	setting(language,Lang),
 1739	\+ lang_ok(Clause,Lang), !, fail.
 1740clause_ok(Clause,_):-
 1741	setting(newvars,NewVars),
 1742	\+ newvars_ok(Clause,NewVars), !, fail.
 1743clause_ok(_,_).
 1744
 1745% check to see if refinement has been produced before
 1746refinement_ok(false,_):- !.
 1747refinement_ok(rls,_):- !.
 1748refinement_ok(_,false):- !.
 1749refinement_ok(_,Entry):-
 1750	(check_cache(Entry,pos,_); check_cache(Entry,neg,_)), !,
 1751	p_message('redundant refinement'),
 1752	fail.
 1753refinement_ok(_,_).
 1754
 1755
 1756% specialised redundancy check with equality theory
 1757% used only to check if equalities introduced by splitting vars make
 1758% literal to be added redundant
 1759split_ok(false,_,_):- !.
 1760split_ok(_,Clause,Lit):-
 1761	functor(Lit,Name,_),
 1762	Name \= '=', 
 1763	copy_term(Clause/Lit,Clause1/Lit1),
 1764	lit_redun(Lit1,Clause1), !,
 1765	p_message('redundant literal'), nl,
 1766	fail.
 1767split_ok(_,_,_).
 1768
 1769lit_redun(Lit,(Head:-Body)):-
 1770	!,
 1771	lit_redun(Lit,(Head,Body)).
 1772lit_redun(Lit,(L1,_)):-
 1773	Lit == L1, !.
 1774lit_redun(Lit,(L1,L2)):-
 1775	!,
 1776	execute_equality(L1),
 1777	lit_redun(Lit,L2).
 1778lit_redun(Lit,L):-
 1779	Lit == L.
 1780
 1781execute_equality(Lit):-
 1782	functor(Lit,'=',2), !,
 1783	Lit.
 1784execute_equality(_).
 1785	
 1786theory_lang_ok([],_).
 1787theory_lang_ok([_-[_,_,_,Clause]|T],Lang):-
 1788        lang_ok(Lang,Clause),
 1789        theory_lang_ok(Lang,T). 
 1790
 1791theory_newvars_ok([],_).
 1792theory_newvars_ok([_-[_,_,_,Clause]|T],NewV):-
 1793        newvars_ok(NewV,Clause),
 1794        theory_newvars_ok(T,NewV). 
 1795
 1796lang_ok((Head:-Body),N):-
 1797	!,
 1798	(lang_ok(N,Head,Body) -> true;
 1799		p_message('outside language bound'),
 1800		fail).
 1801
 1802lang_ok(N,_,_):- N is inf, !.
 1803lang_ok(N,Head,Body):-
 1804	get_psyms((Head,Body),PSymList),
 1805	lang_ok1(PSymList,N).
 1806
 1807newvars_ok((Head:-Body),N):-
 1808	!,
 1809	(newvars_ok(N,Head,Body) -> true;
 1810		p_message('outside newvars bound'),
 1811		fail).
 1812
 1813newvars_ok(N,_,_):- N is inf, !.
 1814newvars_ok(N,Head,Body):-
 1815	vars_in_term([Head],[],HVars),
 1816	goals_to_list(Body,BodyL),
 1817	vars_in_term(BodyL,[],BVars),
 1818        aleph_ord_subtract(BVars,HVars,NewVars),
 1819	length(NewVars,N1),
 1820	N1 =< N.
 1821
 1822get_psyms((L,B),[N/A|Syms]):-
 1823	!,
 1824	functor(L,N,A),
 1825	get_psyms(B,Syms).
 1826get_psyms(true,[]):- !.
 1827get_psyms(L,[N/A]):-
 1828	functor(L,N,A).
 1829
 1830lang_ok1([],_).
 1831lang_ok1([Pred|Preds],N):-
 1832        length(Preds,N0),
 1833        aleph_delete_all(Pred,Preds,Preds1),
 1834        length(Preds1,N1),
 1835        PredOccurs is N0 - N1 + 1,
 1836	PredOccurs =< N,
 1837	lang_ok1(Preds1,N).
 1838
 1839rewrite_clause(sld,_,_,(X:-X)):- !.
 1840rewrite_clause(restricted_sld,true,(Head:-Body),(Head1:-Body1)):- 
 1841	!,
 1842        optimise((Head:-Body),(Head1:-Body1)).
 1843rewrite_clause(_,_,Clause,Clause).
 1844
 1845record_pclauses([]).
 1846record_pclauses([_-[_,_,_,Clause]|T]):-
 1847        split_clause(Clause,Head,Body),
 1848        assertz('$aleph_search'(pclause,pclause(Head,Body))),
 1849        record_pclauses(T).
 1850
 1851% get pos/neg distribution of clause head
 1852reset_clause_prior(S,Head):-
 1853	arg(3,S,Refine),
 1854	Refine = false, !,
 1855	('$aleph_search'(clauseprior,_) -> true;
 1856		get_clause_prior(S,Head,Prior),
 1857		assertz('$aleph_search'(clauseprior,Prior))
 1858	).
 1859reset_clause_prior(S,Head):-
 1860	copy_term(Head,Head1),
 1861	numbervars(Head1,0,_),
 1862	('$aleph_local'(clauseprior,prior(Head1,Prior)) ->
 1863		true;
 1864		get_clause_prior(S,Head,Prior),
 1865		assertz('$aleph_local'(clauseprior,prior(Head1,Prior)))
 1866	),
 1867	retractall('$aleph_search'(clauseprior,_)),
 1868	assertz('$aleph_search'(clauseprior,Prior)).
 1869
 1870get_clause_prior(S,Head,Total-[P-pos,N-neg]):-
 1871	arg(5,S,Greedy),
 1872	arg(14,S,Depth),
 1873	arg(29,S,Time),
 1874	arg(34,S,Proof),
 1875	(Greedy = true ->
 1876		'$aleph_global'(atoms_left,atoms_left(pos,Pos));
 1877		'$aleph_global'(atoms,atoms(pos,Pos))
 1878	),
 1879	'$aleph_global'(atoms_left,atoms_left(neg,Neg)),
 1880	prove(Depth/Time/Proof,pos,(Head:-true),Pos,_,P),
 1881	prove(Depth/Time/Proof,neg,(Head:-true),Neg,_,N),
 1882	Total is P + N.
 1883
 1884get_user_refinement(auto,L,Clause,Template,0):-
 1885        auto_refine(L,Clause,Template).
 1886get_user_refinement(user,_,Clause,Template,0):-
 1887        refine(Clause,Template).
 1888
 1889match_bot(false,Clause,Clause,[]).
 1890match_bot(reduction,Clause,Clause1,Lits):-
 1891	match_lazy_bottom(Clause,Lits),
 1892	get_pclause(Lits,[],Clause1,_,_,_).
 1893match_bot(saturation,Clause,Clause1,Lits):-
 1894	once(get_aleph_clause(Clause,AlephClause)),
 1895	match_bot_lits(AlephClause,[],Lits),
 1896	get_pclause(Lits,[],Clause1,_,_,_).
 1897
 1898match_bot_lits((Lit,Lits),SoFar,[LitNum|LitNums]):-
 1899	!,
 1900	match_bot_lit(Lit,LitNum),
 1901	\+(aleph_member(LitNum,SoFar)),
 1902	match_bot_lits(Lits,[LitNum|SoFar],LitNums).
 1903match_bot_lits(Lit,SoFar,[LitNum]):-
 1904	match_bot_lit(Lit,LitNum),
 1905	\+(aleph_member(LitNum,SoFar)).
 1906
 1907match_bot_lit(Lit,LitNum):-
 1908	'$aleph_sat'(botsize,Last),
 1909	'$aleph_sat_litinfo'(LitNum,_,Lit,_,_,_),
 1910	LitNum >= 0,
 1911	LitNum =< Last.
 1912
 1913match_lazy_bottom(Clause,Lits):-
 1914	once(get_aleph_clause(Clause,AlephClause)),
 1915	copy_term(Clause,CClause),
 1916	split_clause(CClause,CHead,CBody),
 1917	example_saturated(CHead),
 1918	store(stage),
 1919	set(stage,saturation),
 1920	match_lazy_bottom1(CBody),
 1921	reinstate(stage),
 1922	match_bot_lits(AlephClause,[],Lits).
 1923
 1924match_lazy_bottom1(Body):-
 1925	Body,
 1926	match_body_modes(Body),
 1927	fail.
 1928match_lazy_bottom1(_):-
 1929	flatten_matched_atoms(body).
 1930
 1931match_body_modes((CLit,CLits)):-
 1932        !,
 1933        match_mode(body,CLit),
 1934        match_body_modes(CLits).
 1935match_body_modes(CLit):-
 1936        match_mode(body,CLit).
 1937
 1938match_mode(_,true):- !.
 1939match_mode(Loc,CLit):-
 1940	functor(CLit,Name,Arity),
 1941        functor(Mode,Name,Arity),
 1942	(Loc=head ->
 1943		'$aleph_global'(modeh,modeh(_,Mode));
 1944		'$aleph_global'(modeb,modeb(_,Mode))),
 1945        split_args(Mode,Mode,I,O,C),
 1946        (Loc = head ->
 1947		update_atoms(CLit,mode(Mode,O,I,C));
 1948		update_atoms(CLit,mode(Mode,I,O,C))),
 1949	fail.
 1950match_mode(_,_).
 1951
 1952flatten_matched_atoms(Loc):-
 1953        setting(i,IVal),
 1954        (retract('$aleph_sat'(botsize,BSize))-> true;  BSize = 0),
 1955        (retract('$aleph_sat'(lastlit,Last))-> true ; Last = 0),
 1956        (Loc = head ->
 1957                flatten(0,IVal,BSize,BSize1);
 1958                flatten(0,IVal,Last,BSize1)),
 1959        asserta('$aleph_sat'(botsize,BSize1)),
 1960	(Last < BSize1 -> 
 1961        	asserta('$aleph_sat'(lastlit,BSize1));
 1962        	asserta('$aleph_sat'(lastlit,Last))), !.
 1963flatten_matched_atoms(_).
 1964
 1965% integrate head literal into lits database
 1966% used during lazy evaluation of bottom clause
 1967integrate_head_lit(HeadOVars):-
 1968        example_saturated(Example),
 1969	split_args(Example,_,_,Output,_),
 1970	integrate_args(unknown,Example,Output),
 1971        match_mode(head,Example),
 1972	flatten_matched_atoms(head),
 1973        get_ivars1(false,1,HeadOVars), !.
 1974integrate_head_lit([]).
 1975
 1976
 1977get_aleph_clause((Lit:-true),PLit):-
 1978	!,
 1979	get_aleph_lit(Lit,PLit).
 1980get_aleph_clause((Lit:-Lits),(PLit,PLits)):-
 1981	!,
 1982	get_aleph_lit(Lit,PLit),
 1983	get_aleph_lits(Lits,PLits).
 1984get_aleph_clause(Lit,PLit):-
 1985	get_aleph_lit(Lit,PLit).
 1986
 1987get_aleph_lits((Lit,Lits),(PLit,PLits)):-
 1988	!,
 1989	get_aleph_lit(Lit,PLit),
 1990	get_aleph_lits(Lits,PLits).
 1991get_aleph_lits(Lit,PLit):-
 1992	get_aleph_lit(Lit,PLit).
 1993
 1994get_aleph_lit(Lit,PLit):-
 1995	functor(Lit,Name,Arity),
 1996	functor(PLit,Name,Arity),
 1997	get_aleph_lit(Lit,PLit,Arity).
 1998
 1999get_aleph_lit(_,_,0):- !.
 2000get_aleph_lit(Lit,PLit,Arg):-
 2001	arg(Arg,Lit,Term),
 2002	(var(Term) -> arg(Arg,PLit,Term);arg(Arg,PLit,aleph_const(Term))),
 2003	NextArg is Arg - 1,
 2004	get_aleph_lit(Lit,PLit,NextArg), !.
 2005	
 2006% Claudien-style consistency checking as described by De Raedt and Dehaspe, 1996
 2007% currently does not retain actual substitutions that result in inconsistencies
 2008% also, only checks for constraints of the form false:- ...
 2009% this simplifies the check of Body,not(Head) to just Body
 2010ccheck(S,(false:-Body),[],[0,N|_]):-
 2011	(Body = true ->
 2012		N is inf;
 2013		arg(11,S,LContra),
 2014		(LContra = false -> 
 2015        		arg(14,S,Depth),
 2016        		arg(29,S,Time),
 2017			findall(X,(resource_bound_call(Time,Depth,Body),X=1),XL),
 2018			length(XL,N);
 2019			lazy_ccheck(S,Body,N)
 2020		)
 2021	).
 2022
 2023lazy_ccheck(S,Body,N):-
 2024        arg(14,S,Depth),
 2025        arg(17,S,Noise),
 2026        arg(29,S,Time),
 2027	retractall('$aleph_local'(subst_count,_)),
 2028	asserta('$aleph_local'(subst_count,0)),
 2029	resource_bound_call(Time,Depth,Body),
 2030	retract('$aleph_local'(subst_count,N0)),
 2031	N is N0 + 1,
 2032	N > Noise, !.
 2033lazy_ccheck(_,_,N):-
 2034	retract('$aleph_local'(subst_count,N)).
 2035
 2036% posonly formula as described by Muggleton, ILP-96
 2037prove_examples(S,Flag,Contradiction,Entry,Best,CL,L2,Clause,Pos,Rand,PCover,RCover,[P,B,CL,I,G]):-
 2038	arg(4,S,_/Evalfn),
 2039	Evalfn = posonly, !,
 2040        arg(11,S,LazyOnContra),
 2041        ((LazyOnContra = true, Contradiction = true) ->
 2042                prove_lazy_cached(S,Entry,Pos,Rand,PCover,RCover),
 2043                interval_count(PCover,_PC),
 2044                interval_count(RCover,RC);
 2045                prove_pos(S,Flag,Entry,Best,[PC,L2],Clause,Pos,PCover,PC),
 2046                prove_rand(S,Flag,Entry,Clause,Rand,RCover,RC)),
 2047        find_posgain(PCover,P),
 2048        arg(16,S,M), arg(20,S,N),
 2049        GC is (RC+1.0)/(N+2.0), % Laplace correction for small numbers
 2050        A is log(P),
 2051        B is log(GC),
 2052        G is GC*M/P,
 2053        C is CL/P,
 2054        % Sz is CL*M/P,
 2055        % D is M*G,
 2056        %  I is M - D - Sz,
 2057        I is A - B - C.
 2058prove_examples(S,_,_,Entry,_,CL,_,_,Pos,Neg,Pos,Neg,[PC,NC,CL]):-
 2059        arg(10,S,LazyOnCost),
 2060        LazyOnCost = true, !,
 2061        prove_lazy_cached(S,Entry,Pos,Neg,Pos1,Neg1),
 2062        interval_count(Pos1,PC),
 2063        interval_count(Neg1,NC).
 2064prove_examples(S,_,true,Entry,_,CL,_,_,Pos,Neg,Pos,Neg,[PC,NC,CL]):-
 2065        arg(11,S,LazyOnContra),
 2066        LazyOnContra = true, !,
 2067        prove_lazy_cached(S,Entry,Pos,Neg,Pos1,Neg1),
 2068        interval_count(Pos1,PC),
 2069        interval_count(Neg1,NC).
 2070prove_examples(S,Flag,_,Ent,Best,CL,L2,Clause,Pos,Neg,PCover,NCover,[PC,NC,CL]):-
 2071	arg(3,S,RefineOp),
 2072	(RefineOp = false; RefineOp = auto),
 2073        arg(7,S,ClauseLength),
 2074        ClauseLength = CL, !,
 2075	interval_count(Pos,MaxPCount),
 2076        prove_neg(S,Flag,Ent,Best,[MaxPCount,CL],Clause,Neg,NCover,NC),
 2077        arg(17,S,Noise), arg(18,S,MinAcc),
 2078        maxlength_neg_ok(Noise/MinAcc,Ent,MaxPCount,NC),
 2079        prove_pos(S,Flag,Ent,Best,[PC,L2],Clause,Pos,PCover,PC),
 2080        maxlength_neg_ok(Noise/MinAcc,Ent,PC,NC),
 2081	!.
 2082prove_examples(S,Flag,_,Ent,Best,CL,L2,Clause,Pos,Neg,PCover,NCover,[PC,NC,CL]):-
 2083        prove_pos(S,Flag,Ent,Best,[PC,L2],Clause,Pos,PCover,PC),
 2084        prove_neg(S,Flag,Ent,Best,[PC,CL],Clause,Neg,NCover,NC),
 2085	!.
 2086
 2087prove_lazy_cached(S,Entry,Pos,Neg,Pos1,Neg1):-
 2088        arg(8,S,Caching),
 2089	Caching = true, !,
 2090	(check_cache(Entry,pos,Pos1)->
 2091		true;
 2092		add_cache(Entry,pos,Pos),
 2093		Pos1 = Pos),
 2094	(check_cache(Entry,neg,Neg1)->
 2095		true;
 2096		add_cache(Entry,neg,Neg),
 2097		Neg1 = Neg).
 2098prove_lazy_cached(_,_,Pos,Neg,Pos,Neg).
 2099
 2100complete_label(posonly,_,L,L):- !.
 2101complete_label(user,Clause,[P,N,L],[P,N,L,Val]):-
 2102        cost(Clause,[P,N,L],Cost), !,
 2103	Val is -Cost.
 2104complete_label(entropy,_,[P,N,L],[P,N,L,Val]):-
 2105	evalfn(entropy,[P,N,L],Entropy),
 2106	Val is -Entropy, !.
 2107complete_label(gini,_,[P,N,L],[P,N,L,Val]):-
 2108	evalfn(gini,[P,N,L],Gini),
 2109	Val is -Gini, !.
 2110complete_label(EvalFn,_,[P,N,L],[P,N,L,Val]):-
 2111	evalfn(EvalFn,[P,N,L],Val), !.
 2112complete_label(_,_,_,_):-
 2113	p_message1('error'), p_message('incorrect evaluation/cost function'),
 2114	fail.
 2115
 2116% estimate label based on subsampling
 2117estimate_label(Sample,[P,N|Rest],[P1,N1|Rest]):-
 2118	'$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 2119	'$aleph_global'(atoms_left,atoms_left(neg,Neg)),
 2120	interval_count(Pos,PC), interval_count(Neg,NC),
 2121	PFrac is P/Sample,
 2122	NFrac is N/Sample,
 2123	P1 is integer(PFrac*PC),
 2124	N1 is integer(NFrac*NC).
 2125
 2126% get primary and secondary search keys for search
 2127% use [Primary|Secondary] notation as it is the most compact
 2128get_search_keys(bf,[_,_,L,F|_],[L1|F]):-
 2129	!,
 2130	L1 is -1*L.
 2131get_search_keys(df,[_,_,L,F|_],[L|F]):- !.
 2132get_search_keys(_,[_,_,L,F|_],[F|L1]):-
 2133	L1 is -1*L.
 2134
 2135prove_pos(_,_,_,_,_,_,[],[],0):- !.
 2136prove_pos(S,_,Entry,BestSoFar,PosSoFar,Clause,_,PCover,PCount):-
 2137        '$aleph_search'(covers,covers(PCover,PCount)), !,
 2138        pos_ok(S,Entry,BestSoFar,PosSoFar,Clause,PCover).
 2139prove_pos(S,Flag,Entry,BestSoFar,PosSoFar,Clause,Pos,PCover,PCount):-
 2140        prove_cache(Flag,S,pos,Entry,Clause,Pos,PCover,PCount),
 2141        pos_ok(S,Entry,BestSoFar,PosSoFar,Clause,PCover), !.
 2142
 2143prove_neg(S,_,Entry,_,_,_,[],[],0):-
 2144	arg(8,S,Caching),
 2145	(Caching = true -> add_cache(Entry,neg,[]); true), !.
 2146prove_neg(S,Flag,Entry,_,_,Clause,Neg,NCover,NCount):-
 2147	arg(3,S,RefineOp),
 2148	RefineOp = rls,  !,
 2149        prove_cache(Flag,S,neg,Entry,Clause,Neg,NCover,NCount).
 2150prove_neg(_,_,_,_,_,_,_,NCover,NCount):-
 2151        '$aleph_search'(coversn,coversn(NCover,NCount)), !.
 2152prove_neg(S,Flag,Entry,BestSoFar,PosSoFar,Clause,Neg,NCover,NCount):-
 2153        arg(12,S,LazyNegs),
 2154        LazyNegs = true, !,
 2155        lazy_prove_neg(S,Flag,Entry,BestSoFar,PosSoFar,Clause,Neg,NCover,NCount).
 2156prove_neg(S,Flag,Entry,[P,0,L1|_],[P,L2],Clause,Neg,[],0):-
 2157	arg(4,S,bf/coverage),
 2158        L2 is L1 - 1,
 2159	!,
 2160        prove_cache(Flag,S,neg,Entry,Clause,Neg,0,[],0), !.
 2161prove_neg(S,Flag,Entry,[P,N|_],[P,L1],Clause,Neg,NCover,NCount):-
 2162	arg(4,S,bf/coverage),
 2163        !,
 2164        arg(7,S,ClauseLength),
 2165        (ClauseLength = L1 ->
 2166		arg(2,S,Explore),
 2167		(Explore = true -> MaxNegs is N; MaxNegs is N - 1),
 2168                MaxNegs >= 0,
 2169                prove_cache(Flag,S,neg,Entry,Clause,Neg,MaxNegs,NCover,NCount),
 2170		NCount =< MaxNegs;
 2171                prove_cache(Flag,S,neg,Entry,Clause,Neg,NCover,NCount)),
 2172        !.
 2173prove_neg(S,Flag,Entry,_,[P1,L1],Clause,Neg,NCover,NCount):-
 2174        arg(7,S,ClauseLength),
 2175        ClauseLength = L1,  !,
 2176        arg(17,S,Noise), arg(18,S,MinAcc),
 2177        get_max_negs(Noise/MinAcc,P1,N1),
 2178        prove_cache(Flag,S,neg,Entry,Clause,Neg,N1,NCover,NCount),
 2179	NCount =< N1,
 2180        !.
 2181prove_neg(S,Flag,Entry,_,_,Clause,Neg,NCover,NCount):-
 2182        prove_cache(Flag,S,neg,Entry,Clause,Neg,NCover,NCount),
 2183        !.
 2184
 2185prove_rand(S,Flag,Entry,Clause,Rand,RCover,RCount):-
 2186        prove_cache(Flag,S,rand,Entry,Clause,Rand,RCover,RCount),
 2187        !.
 2188
 2189lazy_prove_neg(S,Flag,Entry,[P,N|_],[P,_],Clause,Neg,NCover,NCount):-
 2190	arg(4,S,bf/coverage),
 2191        !,
 2192        MaxNegs is N + 1,
 2193        prove_cache(Flag,S,neg,Entry,Clause,Neg,MaxNegs,NCover,NCount),
 2194        !.
 2195lazy_prove_neg(S,Flag,Entry,_,[P1,_],Clause,Neg,NCover,NCount):-
 2196        arg(17,S,Noise), arg(18,S,MinAcc),
 2197        get_max_negs(Noise/MinAcc,P1,N1),
 2198        MaxNegs is N1 + 1,
 2199        prove_cache(Flag,S,neg,Entry,Clause,Neg,MaxNegs,NCover,NCount),
 2200        !.
 2201
 2202% Bug reported by Daniel Fredouille
 2203% For MiAcc =:= 0, Negs was being set to P1 + 1. Unclear why.
 2204% This definition is as it was up to Aleph 2.
 2205get_max_negs(Noise/MinAcc,P1,N):-
 2206        number(P1), 
 2207	(MinAcc =:= 0.0 -> N is Noise;
 2208        	(N1 is integer((1-MinAcc)*P1/MinAcc),
 2209		(Noise < N1 -> N is Noise; N is N1))
 2210	), !.
 2211get_max_negs(Noise/_,_,Noise).
 2212
 2213
 2214% update_open_list(+SearchKeys,+NodeRef,+Label)
 2215% insert SearchKeys into openlist
 2216update_open_list([K1|K2],NodeRef,Label):-
 2217	assertz('$aleph_search_gain'(K1,K2,NodeRef,Label)),
 2218	retract('$aleph_search'(openlist,OpenList)),
 2219	uniq_insert(descending,[K1|K2],OpenList,List1),
 2220	asserta('$aleph_search'(openlist,List1)).
 2221
 2222pos_ok(S,_,_,_,_,_):-
 2223	arg(3,S,RefineOp),
 2224	(RefineOp = rls; RefineOp = user),  !.
 2225pos_ok(S,Entry,_,[P,_],_,_):-
 2226        arg(13,S,MinPos),
 2227        P < MinPos, !,
 2228        arg(8,S,Caching),
 2229        (Caching = true ->
 2230                add_prune_cache(Entry);
 2231                true),
 2232        fail.
 2233pos_ok(S,Entry,_,[P,_],_,_):-
 2234	arg(40,S,MinPosFrac),
 2235	MinPosFrac > 0.0,
 2236	'$aleph_search'(clauseprior,_-[P1-pos,_]),
 2237	P/P1 < MinPosFrac, !,
 2238        arg(8,S,Caching),
 2239        (Caching = true ->
 2240                add_prune_cache(Entry);
 2241                true),
 2242	fail.
 2243pos_ok(S,_,[_,_,_,C1|_],[P,L],_,_):-
 2244        arg(4,S,_/Evalfn),
 2245	arg(2,S,Explore),
 2246	((Evalfn = user; Explore = true) -> true;
 2247        	evalfn(Evalfn,[P,0,L],C2),
 2248		best_value(Evalfn,S,[P,0,L,C2],Max),
 2249        	Max > C1), !.
 2250
 2251
 2252maxlength_neg_ok(Noise/MinAcc,Entry,P,N):-
 2253	((N > Noise); (P/(P+N) < MinAcc)), !,
 2254        add_prune_cache(Entry),
 2255	fail.
 2256maxlength_neg_ok(_,_,_,_).
 2257
 2258compression_ok(compression,[P,_,L|_]):-
 2259	!,
 2260	P - L + 1 > 0.
 2261compression_ok(_,_).
 2262
 2263length_ok(S,MinLen,ClauseLen,LastD,ExpectedMin,ExpectedCLen):-
 2264        arg(3,S,RefineOp),
 2265        (RefineOp = false  -> L1 = LastD; L1 = 0),
 2266        (L1 < MinLen->ExpectedMin = L1;ExpectedMin = MinLen),
 2267        ExpectedCLen is ClauseLen + ExpectedMin,
 2268        arg(7,S,CLength),
 2269        ExpectedCLen =< CLength, !.
 2270
 2271update_best(S,_,_,_,Best,[P,_,_,F|_]/_,Best):-
 2272        arg(13,S,MinPos),
 2273        arg(19,S,MinScore),
 2274	(P < MinPos;  F is -inf; F < MinScore), !.
 2275update_best(S,_,_,_,Best,[P|_]/_,Best):-
 2276	arg(40,S,MinPosFrac),
 2277	MinPosFrac > 0.0,
 2278	'$aleph_search'(clauseprior,_-[P1-pos,_]),
 2279	P/P1 < MinPosFrac, !.
 2280update_best(S,_,_,_,Best,[P,N,_,_|_]/_,Best):-
 2281        arg(4,S,_/Evalfn),
 2282	Evalfn \= posonly,
 2283	% Evalfn \= user,
 2284        arg(17,S,Noise),
 2285        arg(18,S,MinAcc),
 2286	arg(22,S,Search),
 2287	Total is P + N,
 2288	((N > Noise);(Search \= ic, Total > 0, P/Total < MinAcc)),   !.
 2289update_best(S,Clause,PCover,NCover,Label/_,Label1/Node1,Label1/Node1):-
 2290        Label = [_,_,_,GainE|_],
 2291        Label1 = [_,_,_,Gain1E|_],
 2292	arithmetic_expression_value(GainE,Gain),
 2293	arithmetic_expression_value(Gain1E,Gain1),
 2294        % (Gain1 = inf; Gain = -inf; Gain1 > Gain), !,
 2295	Gain1 > Gain, !,
 2296	retractall('$aleph_search'(selected,_)),
 2297        asserta('$aleph_search'(selected,selected(Label1,Clause,PCover,NCover))),
 2298        arg(35,S,VSearch),
 2299        (VSearch = true ->
 2300		retractall('$aleph_search'(best,_)),
 2301                asserta('$aleph_search'(best,Node1)),
 2302                asserta('$aleph_search'(good,Node1));
 2303                true),
 2304	update_good(Label1,Clause),
 2305        show_clause(newbest,Label1,Clause,Node1),
 2306        record_clause(newbest,Label1,Clause,Node1),
 2307        record_clause(good,Label1,Clause,Node1).
 2308update_best(S,Clause,_,_,Label/Node,Label1/Node1,Label/Node):-
 2309        arg(35,S,VSearch),
 2310        (VSearch = true ->
 2311                asserta('$aleph_search'(good,Node1));
 2312                true),
 2313	update_good(Label1,Clause),
 2314        show_clause(good,Label1,Clause,Node1),
 2315        record_clause(good,Label1,Clause,Node1).
 2316
 2317update_good(Label,Clause):- 
 2318	setting(good,true), !,
 2319	Label = [_,_,L|_],
 2320	setting(check_good,Flag),
 2321	update_good(Flag,L,Label,Clause).
 2322update_good(_,_).
 2323
 2324update_good(_,_,_,_):-
 2325	setting(goodfile,_), !.
 2326update_good(true,L,Label,Clause):-
 2327	'$aleph_good'(L,Label,Clause), !.
 2328update_good(_,L,Label,Clause):-
 2329	assertz('$aleph_good'(L,Label,Clause)),
 2330	(retract('$aleph_search'(last_good,Good)) ->
 2331		Good1 is Good + 1;
 2332		Good1 is 1),
 2333	assertz('$aleph_search'(last_good,Good1)).
 2334
 2335update_best_theory(S,_,_,_,Best,[P,N,_,F|_]/_,Best):-
 2336	arg(17,S,Noise),
 2337	arg(18,S,MinAcc),
 2338	arg(19,S,MinScore),
 2339	(N > Noise; P/(P+N) < MinAcc; F < MinScore),  !.
 2340update_best_theory(_,Theory,PCover,NCover,Label/_,Label1/Node1,Label1/Node1):-
 2341	Label = [_,_,_,GainE|_],
 2342	Label1 = [_,_,_,Gain1E|_],
 2343	arithmetic_expression_value(GainE,Gain),
 2344	arithmetic_expression_value(Gain1E,Gain1),
 2345	Gain1 > Gain, !, 
 2346	retractall('$aleph_search'(selected,_)),
 2347        asserta('$aleph_search'(selected,selected(Label1,Theory,PCover,NCover))),
 2348	show_theory(newbest,Label1,Theory,Node1),
 2349	record_theory(newbest,Label1,Theory,Node1),
 2350	record_theory(good,Label1,Theory,Node1).
 2351update_best_theory(_,Theory,_,_,Best,Label1/_,Best):-
 2352	show_theory(good,Label1,Theory,Node1),
 2353	record_theory(good,Label1,Theory,Node1).
 2354
 2355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 2356% P R U N I N G   C L A U S E S
 2357
 2358get_node([[K1|K2]|_],[K1|K2],Node):-
 2359        '$aleph_search_gain'(K1,K2,Node,_).
 2360get_node([_|Gains],Gain,Node):-
 2361	get_node(Gains,Gain,Node).
 2362
 2363prune_open(S,_,_):-
 2364	arg(25,S,OSize),
 2365	Inf is inf,
 2366	OSize =\= Inf,
 2367        retractall('$aleph_local'(in_beam,_)),
 2368        asserta('$aleph_local'(in_beam,0)),
 2369        '$aleph_search'(openlist,Gains),
 2370        get_node(Gains,[K1|K2],NodeNum),
 2371        '$aleph_local'(in_beam,N),
 2372        (N < OSize->
 2373        	retract('$aleph_local'(in_beam,N)),
 2374                N1 is N + 1,
 2375                asserta('$aleph_local'(in_beam,N1));
 2376		retract('$aleph_search_gain'(K1,K2,NodeNum,_)),
 2377		arg(6,S,Verbose),
 2378                (Verbose < 1 ->
 2379			true;
 2380			p1_message('non-admissible removal'),
 2381			p_message(NodeNum))),
 2382        fail.
 2383prune_open(S,_,_):-
 2384        arg(2,S,Explore),
 2385        arg(3,S,RefineOp),
 2386	(Explore = true; RefineOp = rls; RefineOp = user), !.
 2387prune_open(_,_/N,_/N):- !.
 2388prune_open(S,_,[_,_,_,Best|_]/_):-
 2389        arg(4,S,_/Evalfn),
 2390	built_in_prune(Evalfn),
 2391        '$aleph_search_gain'(_,_,_,Label),
 2392	best_value(Evalfn,S,Label,Best1),
 2393	Best1 =< Best, 
 2394        retract('$aleph_search_gain'(_,_,_,Label)),
 2395	fail.
 2396prune_open(_,_,_).
 2397
 2398built_in_prune(coverage).
 2399built_in_prune(compression).
 2400built_in_prune(posonly).
 2401built_in_prune(laplace).
 2402built_in_prune(wracc).
 2403built_in_prune(mestimate).
 2404built_in_prune(auto_m).
 2405
 2406% pruning for posonly, laplace and m-estimates devised in
 2407%	discussion with James Cussens
 2408% pruning for weighted relative accuracy devised in
 2409%	discussion with Steve Moyle
 2410% corrections to best_value/4 after discussion with
 2411% Mark Reid and James Cussens
 2412best_value(gini,_,_,0.0):- !.
 2413best_value(entropy,_,_,0.0):- !.
 2414best_value(posonly,S,[P,_,L|_],Best):-
 2415	arg(20,S,RSize),
 2416	Best is log(P) + log(RSize+2.0) - (L+1)/P, !.
 2417best_value(wracc,_,[P|_],Best):-
 2418	('$aleph_search'(clauseprior,Total-[P1-pos,_]) ->
 2419		Best is P*(Total - P1)/(Total^2);
 2420		Best is 0.25), !.
 2421best_value(Evalfn,_,[P,_,L|Rest],Best):-
 2422	L1 is L + 1,	% need at least 1 extra literal to achieve best value
 2423	evalfn(Evalfn,[P,0,L1|Rest],Best).
 2424
 2425
 2426get_nextbest(S,NodeRef):-
 2427        arg(22,S,Search),
 2428	select_nextbest(Search,NodeRef).
 2429
 2430% Select the next best node
 2431% Incorporates the changes made by Filip Zelezny to
 2432% achieve the `randomised rapid restart' (or rrr) technique
 2433% within randomised local search
 2434select_nextbest(rls,NodeRef):-
 2435	retractall('$aleph_search'(nextnode,_)),
 2436        setting(rls_type,Type),
 2437        (retract('$aleph_search'(rls_parentstats,stats(PStats,_,_))) -> true; true),
 2438        (rls_nextbest(Type,PStats,NodeRef,Label) ->
 2439                asserta('$aleph_search'(rls_parentstats,stats(Label,[],[]))),
 2440                setting(rls_type,RlsType),
 2441                (RlsType = rrr ->
 2442                      true;
 2443                      assertz('$aleph_search'(nextnode,NodeRef)));
 2444                NodeRef = none), !.
 2445select_nextbest(_,NodeRef):-
 2446	retractall('$aleph_search'(nextnode,_)),
 2447	get_nextbest(NodeRef), !.
 2448select_nextbest(_,none).
 2449
 2450get_nextbest(NodeRef):-
 2451        '$aleph_search'(openlist,[H|_]),
 2452	H = [K1|K2],
 2453        retract('$aleph_search_gain'(K1,K2,NodeRef,_)),
 2454        assertz('$aleph_search'(nextnode,NodeRef)).
 2455get_nextbest(NodeRef):-
 2456        retract('$aleph_search'(openlist,[_|T])),
 2457        asserta('$aleph_search'(openlist,T)),
 2458        get_nextbest(NodeRef), !.
 2459get_nextbest(none).
 2460
 2461rls_nextbest(rrr,_,NodeRef,_):-
 2462        get_nextbest(NodeRef).
 2463rls_nextbest(gsat,_,NodeRef,Label):-
 2464        retract('$aleph_search'(openlist,[H|_])),
 2465	H = [K1|K2],
 2466	asserta('$aleph_search'(openlist,[])),
 2467	findall(N-L,'$aleph_search_gain'(K1,K2,N,L),Choices),
 2468	length(Choices,Last),
 2469	get_random(Last,N),
 2470	aleph_remove_nth(N,Choices,NodeRef-Label,_),
 2471	retractall('$aleph_search_gain'(_,_,_,_)).
 2472rls_nextbest(wsat,PStats,NodeRef,Label):-
 2473	setting(walk,WProb),
 2474	aleph_random(P),
 2475	P >= WProb, !,
 2476	rls_nextbest(gsat,PStats,NodeRef,Label).
 2477rls_nextbest(wsat,PStats,NodeRef,Label):-
 2478	p_message('random walk'),
 2479        retract('$aleph_search'(openlist,_)),
 2480	asserta('$aleph_search'(openlist,[])),
 2481	findall(N-L,'$aleph_search_gain'(_,_,N,L),AllNodes),
 2482	potentially_good(AllNodes,PStats,Choices),
 2483        length(Choices,Last),
 2484        get_random(Last,N),
 2485        aleph_remove_nth(N,Choices,NodeRef-Label,_),
 2486	retractall('$aleph_search_gain'(_,_,_,_)).
 2487rls_nextbest(anneal,[P,N|_],NodeRef,Label):-
 2488	setting(temperature,Temp),
 2489        retract('$aleph_search'(openlist,_)),
 2490	asserta('$aleph_search'(openlist,[])),
 2491	findall(N-L,'$aleph_search_gain'(_,_,N,L),AllNodes),
 2492	length(AllNodes,Last),
 2493	get_random(Last,S),
 2494	aleph_remove_nth(S,AllNodes,NodeRef-Label,_),
 2495	Label = [P1,N1|_],
 2496	Gain is (P1 - N1) - (P - N),
 2497	((P = 1); (Gain >= 0);(aleph_random(R), R < exp(Gain/Temp))).
 2498
 2499potentially_good([],_,[]).
 2500potentially_good([H|T],Label,[H|T1]):-
 2501        H = _-Label1,
 2502        potentially_good(Label,Label1), !,
 2503        potentially_good(T,Label,T1).
 2504potentially_good([_|T],Label,T1):-
 2505        potentially_good(T,Label,T1).
 2506
 2507potentially_good([1|_],[P1|_]):-
 2508        !,
 2509        P1 > 1.
 2510potentially_good([P,_,L|_],[P1,_,L1|_]):-
 2511        L1 =< L, !,
 2512        P1 > P.
 2513potentially_good([_,N|_],[_,N1|_]):-
 2514        N1 < N.
 2515
 2516
 2517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 2518% P R O V E
 2519
 2520% prove with caching
 2521% if entry exists in cache, then return it
 2522% otherwise find and cache cover 
 2523% if ``exact'' flag is set then only check proof for examples
 2524% in the part left over due to lazy theorem-proving
 2525% ideas in caching developed in discussions with James Cussens
 2526
 2527prove_cache(exact,S,Type,Entry,Clause,Intervals,IList,Count):-
 2528	!,
 2529	(Intervals = Exact/Left ->
 2530        	arg(14,S,Depth),
 2531        	arg(29,S,Time),
 2532        	arg(34,S,Proof),
 2533        	prove(Depth/Time/Proof,Type,Clause,Left,IList1,Count1),
 2534		aleph_append(IList1,Exact,IList),
 2535		interval_count(Exact,Count0),
 2536		Count is Count0 + Count1;
 2537		IList = Intervals,
 2538		interval_count(IList,Count)),
 2539        arg(8,S,Caching),
 2540        (Caching = true -> add_cache(Entry,Type,IList); true).
 2541prove_cache(upper,S,Type,Entry,Clause,Intervals,IList,Count):-
 2542        arg(8,S,Caching),
 2543        Caching = true, !,
 2544        arg(14,S,Depth),
 2545        arg(29,S,Time),
 2546        arg(34,S,Proof),
 2547        (check_cache(Entry,Type,Cached)->
 2548                prove_cached(S,Type,Entry,Cached,Clause,Intervals,IList,Count);
 2549                prove_intervals(Depth/Time/Proof,Type,Clause,Intervals,IList,Count),
 2550                add_cache(Entry,Type,IList)).
 2551prove_cache(upper,S,Type,_,Clause,Intervals,IList,Count):-
 2552        arg(14,S,Depth),
 2553        arg(29,S,Time),
 2554        arg(34,S,Proof),
 2555	(Intervals = Exact/Left ->
 2556		aleph_append(Left,Exact,IList1),
 2557        	prove(Depth/Time/Proof,Type,Clause,IList1,IList,Count);
 2558        	prove(Depth/Time/Proof,Type,Clause,Intervals,IList,Count)).
 2559
 2560prove_intervals(DepthTime,Type,Clause,I1/Left,IList,Count):- 
 2561	!,
 2562	aleph_append(Left,I1,Intervals),
 2563	prove(DepthTime,Type,Clause,Intervals,IList,Count).
 2564prove_intervals(DepthTime,Type,Clause,Intervals,IList,Count):- 
 2565	prove(DepthTime,Type,Clause,Intervals,IList,Count).
 2566
 2567prove_cached(S,Type,Entry,I1/Left,Clause,Intervals,IList,Count):-
 2568        !,
 2569        arg(14,S,Depth),
 2570        arg(29,S,Time),
 2571        arg(34,S,Proof),
 2572        prove(Depth/Time/Proof,Type,Clause,Left,I2,_),
 2573        aleph_append(I2,I1,I),
 2574        (Type = pos ->
 2575                arg(5,S,Greedy),
 2576                (Greedy = true ->
 2577                        intervals_intersection(I,Intervals,IList);
 2578                        IList = I);
 2579                IList = I),
 2580        interval_count(IList,Count),
 2581        update_cache(Entry,Type,IList).
 2582prove_cached(S,Type,Entry,I1,_,Intervals,IList,Count):-
 2583	(Type = pos -> arg(5,S,Greedy),
 2584		(Greedy = true ->
 2585			intervals_intersection(I1,Intervals,IList);
 2586			IList = I1);
 2587		IList = I1),
 2588	interval_count(IList,Count),
 2589	update_cache(Entry,Type,IList).
 2590
 2591% prove at most Max atoms
 2592prove_cache(exact,S,Type,Entry,Clause,Intervals,Max,IList,Count):-
 2593	!,
 2594	(Intervals = Exact/Left ->
 2595		interval_count(Exact,Count0),
 2596		Max1 is Max - Count0,
 2597        	arg(12,S,LNegs),
 2598        	arg(14,S,Depth),
 2599        	arg(29,S,Time),
 2600        	arg(34,S,Proof),
 2601        	prove(LNegs/false,Depth/Time/Proof,Type,Clause,Left,Max1,IList1,Count1),
 2602		aleph_append(IList1,Exact,Exact1),
 2603		find_lazy_left(S,Type,Exact1,Left1),
 2604		IList = Exact1/Left1,
 2605		Count is Count0 + Count1;
 2606		IList = Intervals,
 2607		interval_count(Intervals,Count)),
 2608        arg(8,S,Caching),
 2609        (Caching = true -> add_cache(Entry,Type,IList); true).
 2610prove_cache(upper,S,Type,Entry,Clause,Intervals,Max,IList,Count):-
 2611        arg(8,S,Caching),
 2612        Caching = true, !,
 2613        (check_cache(Entry,Type,Cached)->
 2614                prove_cached(S,Type,Entry,Cached,Clause,Intervals,Max,IList,Count);
 2615                (prove_intervals(S,Type,Clause,Intervals,Max,IList1,Count)->
 2616                        find_lazy_left(S,Type,IList1,Left1),
 2617                        add_cache(Entry,Type,IList1/Left1),
 2618			IList = IList1/Left1,
 2619                        retractall('$aleph_local'(example_cache,_));
 2620                        collect_example_cache(IList),
 2621                        add_cache(Entry,Type,IList),
 2622                        fail)).
 2623prove_cache(upper,S,Type,_,Clause,Intervals,Max,IList/Left1,Count):-
 2624        arg(8,S,Caching),
 2625        arg(12,S,LNegs),
 2626        arg(14,S,Depth),
 2627        arg(29,S,Time),
 2628        arg(34,S,Proof),
 2629	(Intervals = Exact/Left ->
 2630		aleph_append(Left,Exact,IList1),
 2631        	prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,IList1,Max,IList,Count);
 2632        	prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,Intervals,Max,IList,Count)),
 2633	find_lazy_left(S,Type,IList,Left1).
 2634
 2635prove_intervals(S,Type,Clause,I1/Left,Max,IList,Count):-
 2636        !,
 2637        arg(8,S,Caching),
 2638        arg(12,S,LNegs),
 2639        arg(14,S,Depth),
 2640        arg(29,S,Time),
 2641        arg(34,S,Proof),
 2642        aleph_append(Left,I1,Intervals),
 2643        prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,Intervals,Max,IList,Count).
 2644prove_intervals(S,Type,Clause,Intervals,Max,IList,Count):-
 2645        arg(8,S,Caching),
 2646        arg(12,S,LNegs),
 2647        arg(14,S,Depth),
 2648        arg(29,S,Time),
 2649        arg(34,S,Proof),
 2650        prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,Intervals,Max,IList,Count).
 2651
 2652
 2653prove_cached(S,Type,Entry, I1/Left,Clause,_,Max,IList/Left1,Count):-
 2654        !,
 2655        arg(8,S,Caching),
 2656        arg(12,S,LNegs),
 2657        arg(14,S,Depth),
 2658        arg(29,S,Time),
 2659        arg(34,S,Proof),
 2660        interval_count(I1,C1),
 2661        Max1 is Max - C1,
 2662        Max1 >= 0,
 2663        (prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,Left,Max1,I2,C2)->
 2664                aleph_append(I2,I1,IList),
 2665                Count is C2 + C1,
 2666                find_lazy_left(S,Type,IList,Left1),
 2667                update_cache(Entry,Type,IList/Left1),
 2668                retractall('$aleph_local'(example_cache,_));
 2669                collect_example_cache(I2/Left1),
 2670                aleph_append(I2,I1,IList),
 2671                update_cache(Entry,Type,IList/Left1),
 2672                fail).
 2673prove_cached(_,neg,_, I1/L1,_,_,_,I1/L1,C1):-
 2674	!,
 2675	interval_count(I1,C1).
 2676prove_cached(S,_,_,I1,_,_,Max,I1,C1):-
 2677	interval_count(I1,C1),
 2678	arg(12,S,LNegs),
 2679	(LNegs = true ->true; C1 =< Max).
 2680
 2681collect_example_cache(Intervals/Left):-
 2682	retract('$aleph_local'(example_cache,[Last|Rest])),
 2683	aleph_reverse([Last|Rest],IList),
 2684	list_to_intervals1(IList,Intervals),
 2685	Next is Last + 1,
 2686	'$aleph_global'(size,size(neg,LastN)),
 2687	(Next > LastN -> Left = []; Left = [Next-LastN]).
 2688
 2689find_lazy_left(S,_,_,[]):-
 2690        arg(12,S,LazyNegs),
 2691        LazyNegs = false, !.
 2692find_lazy_left(_,_,[],[]).
 2693find_lazy_left(S,Type,[_-F],Left):-
 2694        !,
 2695        F1 is F + 1,
 2696	(Type = pos -> arg(16,S,Last);
 2697		(Type = neg -> arg(24,S,Last);
 2698			(Type = rand -> arg(20,S,Last); Last = F))),
 2699        (F1 > Last -> Left = []; Left = [F1-Last]).
 2700find_lazy_left(S,Type,[_|T1],Left):-
 2701        find_lazy_left(S,Type,T1,Left).
 2702
 2703
 2704% prove atoms specified by Type and index set using Clause.
 2705% dependent on data structure used for index set:
 2706% currently index set is a list of intervals
 2707% return atoms proved and their count
 2708% if tail-recursive version is needed see below
 2709
 2710prove(_,_,_,[],[],0).
 2711prove(Flags,Type,Clause,[Interval|Intervals],IList,Count):-
 2712	index_prove(Flags,Type,Clause,Interval,I1,C1),
 2713	prove(Flags,Type,Clause,Intervals,I2,C2),
 2714	aleph_append(I2,I1,IList),
 2715	Count is C1 + C2.
 2716
 2717
 2718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 2719% T A I L - R E C U R S I V E  P R O V E/6
 2720 
 2721% use this rather than the prove/6 above for tail recursion
 2722% written by James Cussens
 2723 
 2724
 2725% prove(DepthTime,Type,Clause,Intervals,IList,Count):-
 2726       % prove2(Intervals,DepthTime,Type,Clause,0,IList,Count).
 2727 
 2728% code for tail recursive cover testing
 2729% starts here
 2730
 2731% when we know that Sofar is a variable.
 2732prove2([],_,_,_,Count,[],Count).
 2733prove2([Current-Finish|Intervals],Depth/Time/Proof,Type,(Head:-Body),InCount,Sofar,OutCount) :-
 2734	example(Current,Type,Example),
 2735	\+ prove1(Proof,Depth/Time,Example,(Head:-Body)), %uncovered
 2736        !,
 2737        (Current>=Finish ->
 2738            prove2(Intervals,Depth/Time/Proof,Type,(Head:-Body),InCount,Sofar,OutCount);
 2739            Next is Current+1,!,
 2740            prove2([Next-Finish|Intervals],Depth/Time/Proof,Type,(Head:-Body),InCount,Sofar,OutCount)
 2741        ).
 2742prove2([Current-Finish|Intervals],ProofFlags,Type,Clause,InCount,Sofar,OutCount) :-
 2743        (Current>=Finish ->
 2744            Sofar=[Current-Current|Rest],
 2745            MidCount is InCount+1,!,
 2746            prove2(Intervals,ProofFlags,Type,Clause,MidCount,Rest,OutCount);
 2747            Next is Current+1,
 2748            Sofar=[Current-_Last|_Rest],!,
 2749            prove3([Next-Finish|Intervals],ProofFlags,Type,Clause,InCount,Sofar,OutCount)
 2750        ).
 2751 
 2752%when Sofar is not a variable
 2753prove3([Current-Finish|Intervals],Depth/Time/Proof,Type,(Head:-Body),InCount,Sofar,OutCount) :-
 2754	example(Current,Type,Example),
 2755	\+ prove1(Proof,Depth/Time,Example,(Head:-Body)), %uncovered
 2756        !,
 2757        Last is Current-1, %found some previously
 2758        Sofar=[Start-Last|Rest], %complete found interval
 2759        MidCount is InCount+Current-Start,
 2760        (Current>=Finish ->
 2761            prove2(Intervals,Depth/Time/Proof,Type,(Head:-Body),MidCount,Rest,OutCount);
 2762            Next is Current+1,!,
 2763            prove2([Next-Finish|Intervals],Depth/Time/Proof,Type,(Head:-Body),MidCount,Rest,OutCount)
 2764        ).
 2765prove3([Current-Finish|Intervals],ProofFlags,Type,Clause,InCount,Sofar,OutCount) :-
 2766        (Current>=Finish ->
 2767            Sofar=[Start-Finish|Rest],
 2768            MidCount is InCount+Finish-Start+1,!,
 2769            prove2(Intervals,ProofFlags,Type,Clause,MidCount,Rest,OutCount);
 2770            Next is Current+1,!,
 2771            prove3([Next-Finish|Intervals],ProofFlags,Type,Clause,InCount,Sofar,OutCount)
 2772        ).
 2773 
 2774 
 2775% code for tail recursive cover testing
 2776% ends here
 2777
 2778index_prove(_,_,_,Start-Finish,[],0):-
 2779	Start > Finish, !.
 2780index_prove(ProofFlags,Type,Clause,Start-Finish,IList,Count):-
 2781	index_prove1(ProofFlags,Type,Clause,Start,Finish,Last),
 2782	Last0 is Last - 1 ,
 2783	Last1 is Last + 1,
 2784	(Last0 >= Start->
 2785		index_prove(ProofFlags,Type,Clause,Last1-Finish,Rest,Count1),
 2786		IList = [Start-Last0|Rest],
 2787		Count is Last - Start + Count1;
 2788		index_prove(ProofFlags,Type,Clause,Last1-Finish,IList,Count)).
 2789
 2790prove1(G):-
 2791	depth_bound_call(G), !.
 2792
 2793prove1(user,_,Example,Clause):-
 2794	prove(Clause,Example), !.
 2795prove1(restricted_sld,Depth/Time,Example,(Head:-Body)):-
 2796	\+((\+(((Example = Head),resource_bound_call(Time,Depth,Body))))), !.
 2797prove1(sld,Depth/Time,Example,_):-
 2798	\+(\+(resource_bound_call(Time,Depth,Example))), !.
 2799	
 2800index_prove1(_,_,_,Num,Last,Num):-
 2801	Num > Last, !.
 2802index_prove1(Depth/Time/Proof,Type,Clause,Num,Finish,Last):-
 2803	example(Num,Type,Example),
 2804	prove1(Proof,Depth/Time,Example,Clause), !,
 2805	Num1 is Num + 1,
 2806	index_prove1(Depth/Time/Proof,Type,Clause,Num1,Finish,Last).
 2807index_prove1(_,_,_,Last,_,Last).
 2808
 2809
 2810% proves at most Max atoms using Clause.
 2811
 2812prove(_,_,_,_,[],_,[],0).
 2813prove(Flags,ProofFlags,Type,Clause,[Interval|Intervals],Max,IList,Count):-
 2814        index_prove(Flags,ProofFlags,Type,Clause,Interval,Max,I1,C1), !,
 2815        Max1 is Max - C1,
 2816        prove(Flags,ProofFlags,Type,Clause,Intervals,Max1,I2,C2),
 2817        aleph_append(I2,I1,IList),
 2818        Count is C1 + C2.
 2819
 2820
 2821index_prove(_,_,_,_,Start-Finish,_,[],0):-
 2822        Start > Finish, !.
 2823index_prove(Flags,ProofFlags,Type,Clause,Start-Finish,Max,IList,Count):-
 2824        index_prove1(Flags,ProofFlags,Type,Clause,Start,Finish,0,Max,Last),
 2825        Last0 is Last - 1 ,
 2826        Last1 is Last + 1,
 2827        (Last0 >= Start->
 2828                Max1 is Max - Last + Start,
 2829		((Max1 = 0, Flags = true/_) ->
 2830                        Rest = [], Count1 = 0;
 2831                	index_prove(Flags,ProofFlags,Type,Clause,Last1-Finish,
 2832					Max1,Rest,Count1)),
 2833                IList = [Start-Last0|Rest],
 2834                Count is Last - Start + Count1;
 2835                index_prove(Flags,ProofFlags,Type,Clause,Last1-Finish,Max,IList,Count)).
 2836
 2837index_prove1(false/_,_,_,_,_,_,Proved,Allowed,_):-
 2838        Proved > Allowed, !, fail.
 2839index_prove1(_,_,_,_,Num,Last,_,_,Num):-
 2840        Num > Last, !.
 2841index_prove1(true/_,_,_,_,Num,_,Allowed,Allowed,Num):- !.
 2842index_prove1(LNegs/Caching,Depth/Time/Proof,Type,Clause,Num,Finish,Proved,Allowed,Last):-
 2843	example(Num,Type,Example),
 2844	prove1(Proof,Depth/Time,Example,Clause), !,
 2845        Num1 is Num + 1,
 2846        Proved1 is Proved + 1,
 2847        (Caching = true ->
 2848                (retract('$aleph_local'(example_cache,L)) ->
 2849                        asserta('$aleph_local'(example_cache,[Num|L]));
 2850                        asserta('$aleph_local'(example_cache,[Num])));
 2851                true),
 2852        index_prove1(LNegs/Caching,Depth/Time/Proof,Type,Clause,Num1,Finish,Proved1,Allowed,Last).
 2853index_prove1(_,_,_,_,Last,_,_,_,Last).
 2854
 2855% resource_bound_call(Time,Depth,Goals)
 2856%	attempt to prove Goals using depth bounded theorem-prover
 2857%	in at most Time secs
 2858resource_bound_call(T,Depth,Goals):-
 2859	Inf is inf,
 2860	T =:= Inf,
 2861	!,
 2862	depth_bound_call(Goals,Depth).
 2863resource_bound_call(T,Depth,Goals):-
 2864        catch(time_bound_call(T,prooflimit,depth_bound_call(Goals,Depth)),
 2865		prooflimit,fail).
 2866
 2867time_bound_call(T,Exception,Goal):-
 2868	alarm(T,throw(Exception),X),
 2869        (Goal -> remove_alarm(X); remove_alarm(X), fail).
 2870
 2871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 2872% C A C H I N G
 2873
 2874clear_cache:-
 2875	retractall('$aleph_search_cache'(_)),
 2876	retractall('$aleph_search_prunecache'(_)).
 2877
 2878check_cache(Entry,Type,I):-
 2879	Entry \= false,
 2880        '$aleph_search_cache'(Entry), !,
 2881        functor(Entry,_,Arity),
 2882        (Type = pos -> Arg is Arity - 1; Arg is Arity),
 2883        arg(Arg,Entry,I),
 2884	nonvar(I).
 2885
 2886add_cache(false,_,_):- !.
 2887add_cache(Entry,Type,I):-
 2888        (retract('$aleph_search_cache'(Entry))-> true ; true),
 2889        functor(Entry,_,Arity),
 2890        (Type = pos -> Arg is Arity - 1; Arg is Arity),
 2891        (arg(Arg,Entry,I)-> asserta('$aleph_search_cache'(Entry));
 2892                        true), !.
 2893
 2894update_cache(Entry,Type,I):-
 2895        Entry \= false,
 2896        functor(Entry,Name,Arity),
 2897        (Type = pos -> Arg is Arity - 1; Arg is Arity),
 2898        arg(Arg,Entry,OldI),
 2899        OldI = _/_,
 2900        retract('$aleph_search_cache'(Entry)),
 2901        functor(NewEntry,Name,Arity),
 2902        Arg0 is Arg - 1,
 2903        copy_args(Entry,NewEntry,1,Arg0),
 2904        arg(Arg,NewEntry,I),
 2905        Arg1 is Arg + 1,
 2906        copy_args(Entry,NewEntry,Arg1,Arity),
 2907        asserta('$aleph_search_cache'(NewEntry)), !.
 2908update_cache(_,_,_).
 2909
 2910	
 2911add_prune_cache(false):- !.
 2912add_prune_cache(Entry):-
 2913	('$aleph_global'(caching,set(caching,true))->
 2914		functor(Entry,_,Arity),
 2915		A1 is Arity - 2,
 2916		arg(A1,Entry,Clause),
 2917		asserta('$aleph_search_prunecache'(Clause));
 2918		true).
 2919
 2920get_cache_entry(Max,Clause,Entry):-
 2921        skolemize(Clause,Head,Body,0,_),
 2922	length(Body,L1),
 2923	Max >= L1 + 1,
 2924        aleph_hash_term([Head|Body],Entry), !.
 2925get_cache_entry(_,_,false).
 2926
 2927% upto 3-argument indexing using predicate names in a clause
 2928aleph_hash_term([L0,L1,L2,L3,L4|T],Entry):-
 2929        !,
 2930        functor(L1,P1,_), functor(L2,P2,_),
 2931        functor(L3,P3,_), functor(L4,P4,_),
 2932        functor(Entry,P4,6),
 2933        arg(1,Entry,P2), arg(2,Entry,P3),
 2934        arg(3,Entry,P1), arg(4,Entry,[L0,L1,L2,L3,L4|T]).
 2935aleph_hash_term([L0,L1,L2,L3],Entry):-
 2936        !,
 2937        functor(L1,P1,_), functor(L2,P2,_),
 2938        functor(L3,P3,_),
 2939        functor(Entry,P3,5),
 2940        arg(1,Entry,P2), arg(2,Entry,P1),
 2941        arg(3,Entry,[L0,L1,L2,L3]).
 2942aleph_hash_term([L0,L1,L2],Entry):-
 2943        !,
 2944        functor(L1,P1,_), functor(L2,P2,_),
 2945        functor(Entry,P2,4),
 2946        arg(1,Entry,P1), arg(2,Entry,[L0,L1,L2]).
 2947aleph_hash_term([L0,L1],Entry):-
 2948        !,
 2949        functor(L1,P1,_),
 2950        functor(Entry,P1,3),
 2951        arg(1,Entry,[L0,L1]).
 2952aleph_hash_term([L0],Entry):-
 2953        functor(L0,P0,_),
 2954        functor(Entry,P0,3),
 2955        arg(1,Entry,[L0]).
 2956%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 2957% T R E E S
 2958
 2959construct_tree(Type):-
 2960	setting(searchtime,Time),
 2961	Inf is inf,
 2962        Time =\= Inf,
 2963        SearchTime is integer(Time),
 2964        SearchTime > 0, !,
 2965	catch(time_bound_call(SearchTime,searchlimit,find_tree(Type)),
 2966		searchlimit,p_message('Time limit reached')).
 2967construct_tree(Type):-
 2968	find_tree(Type).
 2969
 2970% find_tree(Type) where Type is one of
 2971%      classification, regression, class_probability
 2972find_tree(Type):-
 2973	retractall('$aleph_search'(tree,_)),
 2974	retractall('$aleph_search'(tree_besterror,_)),
 2975	retractall('$aleph_search'(tree_gain,_)),
 2976	retractall('$aleph_search'(tree_lastleaf,_)),
 2977	retractall('$aleph_search'(tree_leaf,_)),
 2978	retractall('$aleph_search'(tree_newleaf,_)),
 2979	retractall('$aleph_search'(tree_startdistribution,_)),
 2980	get_start_distribution(Type,Distribution),
 2981	asserta('$aleph_search'(tree_startdistribution,d(Type,Distribution))),
 2982	'$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 2983	setting(dependent,Argno),
 2984	p_message('constructing tree'),
 2985	stopwatch(StartClock),
 2986	get_search_settings(S),
 2987	auto_refine(false,Head),
 2988	gen_leaf(Leaf),
 2989	eval_treenode(S,Type,(Head:-true),[Argno],Pos,Examples,N,Cost),
 2990	asserta('$aleph_search'(tree_leaf,l(Leaf,Leaf,[Head,Cost,N],Examples))),
 2991	find_tree1([Leaf],S,Type,[Argno]),
 2992	prune_rules(S,Type,[Argno]),
 2993	stopwatch(StopClock),
 2994	add_tree(S,Type,[Argno]),
 2995	Time is StopClock - StartClock,
 2996	p1_message('construction time'), p_message(Time).
 2997
 2998get_start_distribution(regression,0-[0,0]):- !.
 2999get_start_distribution(model,0-[0,0]):-
 3000	setting(evalfn,mse), !.
 3001get_start_distribution(model,0-Distribution):- 
 3002	setting(evalfn,accuracy), !,
 3003	(setting(classes,Classes) -> true;
 3004		!,
 3005		p_message('missing setting for classes'),
 3006		fail),
 3007	initialise_distribution(Classes,Distribution), !.
 3008get_start_distribution(Tree,0-Distribution):-
 3009	(Tree = classification; Tree = class_probability),
 3010	(setting(classes,Classes) -> true;
 3011		!,
 3012		p_message('missing setting for classes'),
 3013		fail),
 3014	initialise_distribution(Classes,Distribution), !.
 3015get_start_distribution(_,_):-
 3016	p_message('incorrect/missing setting for tree_type or evalfn'),
 3017	fail.
 3018
 3019initialise_distribution([],[]).
 3020initialise_distribution([Class|Classes],[0-Class|T]):-
 3021	initialise_distribution(Classes,T).
 3022
 3023laplace_correct([],[]).
 3024laplace_correct([N-Class|Classes],[N1-Class|T]):-
 3025	N1 is N + 1,
 3026	laplace_correct(Classes,T).
 3027
 3028find_tree1([],_,_,_).
 3029find_tree1([Leaf|Leaves],S,Type,Predict):-
 3030	can_split(S,Type,Predict,Leaf,Left,Right), !,
 3031	split_leaf(Leaf,Left,Right,NewLeaves),
 3032	aleph_append(NewLeaves,Leaves,LeavesLeft),
 3033	find_tree1(LeavesLeft,S,Type,Predict).
 3034find_tree1([_|LeavesLeft],S,Type,Predict):-
 3035	find_tree1(LeavesLeft,S,Type,Predict).
 3036
 3037prune_rules(S,Tree,Predict):-
 3038	setting(prune_tree,true), 
 3039	prune_rules1(Tree,S,Predict), !.
 3040prune_rules(_,_,_).
 3041
 3042% pessimistic pruning by employing corrections to observed errors
 3043prune_rules1(class_probability,_,_):-
 3044	p_message('no pruning for class probability trees'), !.
 3045prune_rules1(model,_,_):-
 3046	p_message('no pruning for model trees'), !.
 3047prune_rules1(Tree,S,Predict):-
 3048	p_message('pruning clauses'),
 3049	'$aleph_search'(tree_leaf,l(Leaf,Parent,Clause,Examples)),
 3050	prune_rule(Tree,S,Predict,Clause,Examples,NewClause,NewExamples),
 3051	retract('$aleph_search'(tree_leaf,l(Leaf,Parent,Clause,Examples))),
 3052	asserta('$aleph_search'(tree_newleaf,l(Leaf,Parent,NewClause,NewExamples))),
 3053	fail.
 3054prune_rules1(_,_,_):-
 3055	retract('$aleph_search'(tree_newleaf,l(Leaf,Parent,NewClause,NewExamples))),
 3056	asserta('$aleph_search'(tree_leaf,l(Leaf,Parent,NewClause,NewExamples))),
 3057	fail.
 3058prune_rules1(_,_,_).
 3059
 3060prune_rule(Tree,S,PredictArg,[Clause,_,N],Examples,[PrunedClause,E1,NCov],NewEx):-
 3061	node_stats(Tree,Examples,PredictArg,Total-Distribution),
 3062	leaf_prediction(Tree,Total-Distribution,_,Incorrect),
 3063	estimate_error(Tree,Incorrect,Total,Upper),
 3064	split_clause(Clause,Head,Body),
 3065	goals_to_list(Body,BodyL),
 3066	arg(14,S,Depth),
 3067	arg(29,S,Time),
 3068	arg(34,S,Proof),
 3069	greedy_prune_rule(Tree,Depth/Time/Proof,PredictArg,[Head|BodyL],Upper,C1L,E1),
 3070	list_to_clause(C1L,PrunedClause),
 3071	% p1_message('pruned clause'), p_message(Clause),
 3072	% p_message('to'),
 3073	% p_message(PrunedClause),
 3074	(E1 < Upper ->
 3075		'$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 3076        	prove(Depth/Time/Proof,pos,PrunedClause,Pos,NewEx,NCov);
 3077		NewEx = Examples,
 3078		NCov = N).
 3079
 3080
 3081% estimate error using binomial distribution as done in C4.5
 3082estimate_error(classification,Incorrect,Total,Error):-
 3083	setting(confidence,Conf),
 3084	estimate_error(1.0/0.0,0.0/1.0,Conf,Total,Incorrect,Error).
 3085
 3086% estimate upper bound on sample std deviation by
 3087% assuming the n values in a leaf are normally distributed.
 3088% In this case, a (1-alpha)x100 confidence interval for the
 3089% variance is (n-1)s^2/X^2(alpha/2) =< var =< (n-1)s^2/X^2(1-alpha/2)
 3090estimate_error(regression,Sd,1,Sd):- !.
 3091estimate_error(regression,Sd,N,Upper):-
 3092	(setting(confidence,Conf) -> true; Conf = 0.95),
 3093	Alpha is 1.0 - Conf,
 3094	DF is N - 1,
 3095	Prob is 1 - Alpha/2,
 3096	chi_square(DF,Prob,ChiSq),
 3097	Upper is Sd*sqrt((N-1)/ChiSq).
 3098
 3099bound_error(classification,Error,Total,Lower,Upper):-
 3100	(setting(confidence,Alpha) -> true; Alpha = 0.95),
 3101	approx_z(Alpha,Z),
 3102	Lower is Error - Z*sqrt(Error*(1-Error)/Total),
 3103	Upper is Error + Z*sqrt(Error*(1-Error)/Total).
 3104
 3105approx_z(P,2.58):- P >= 0.99, !.
 3106approx_z(P,Z):- P >= 0.98, !, Z is 2.33 + (P-0.98)*(2.58-2.33)/(0.99-0.98).
 3107approx_z(P,Z):- P >= 0.95, !, Z is 1.96 + (P-0.95)*(2.33-1.96)/(0.98-0.95).
 3108approx_z(P,Z):- P >= 0.90, !, Z is 1.64 + (P-0.90)*(1.96-1.64)/(0.95-0.90).
 3109approx_z(P,Z):- P >= 0.80, !, Z is 1.28 + (P-0.80)*(1.64-1.28)/(0.90-0.80).
 3110approx_z(P,Z):- P >= 0.68, !, Z is 1.00 + (P-0.68)*(1.28-1.00)/(0.80-0.68).
 3111approx_z(P,Z):- P >= 0.50, !, Z is 0.67 + (P-0.50)*(1.00-0.67)/(0.68-0.50).
 3112approx_z(_,0.67).
 3113
 3114greedy_prune_rule(Tree,Flags,PredictArg,Clause,Err0,NewClause,BestErr):-
 3115	greedy_prune_rule1(Tree,Flags,PredictArg,Clause,Err0,Clause1,Err1),
 3116	Clause \= Clause1, !,
 3117	greedy_prune_rule(Tree,Flags,PredictArg,Clause1,Err1,NewClause,BestErr).
 3118greedy_prune_rule(_,_,_,C,E,C,E).
 3119
 3120
 3121greedy_prune_rule1(Tree,Flags,PredictArg,[Head|Body],Err0,_,_):-
 3122	retractall('$aleph_search'(tree_besterror,_)),
 3123	asserta('$aleph_search'(tree_besterror,besterror([Head|Body],Err0))),
 3124	'$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 3125	aleph_delete(_,Body,Left),
 3126	strip_negs(Left,Body1),
 3127	aleph_mode_linked([Head|Body1]),
 3128	list_to_clause([Head|Left],Clause),
 3129        prove(Flags,pos,Clause,Pos,Ex1,_),
 3130	node_stats(Tree,Ex1,PredictArg,Total-Distribution),
 3131	leaf_prediction(Tree,Total-Distribution,_,Incorrect),
 3132	estimate_error(Tree,Incorrect,Total,Upper),
 3133	'$aleph_search'(tree_besterror,besterror(_,BestError)),
 3134	Upper =< BestError, 
 3135	retract('$aleph_search'(tree_besterror,besterror(_,BestError))),
 3136	asserta('$aleph_search'(tree_besterror,besterror([Head|Left],Upper))),
 3137	fail.
 3138greedy_prune_rule1(_,_,_,_,_,Clause1,Err1):-
 3139	retract('$aleph_search'(tree_besterror,besterror(Clause1,Err1))).
 3140
 3141strip_negs([],[]).
 3142strip_negs([not(L)|T],[L|T1]):-
 3143	!,
 3144	strip_negs(T,T1).
 3145strip_negs([L|T],[L|T1]):-
 3146	strip_negs(T,T1).
 3147	
 3148add_tree(_,Tree,Predict):-
 3149	retract('$aleph_search'(tree_leaf,l(_,_,Leaf,Examples))),
 3150	Leaf = [Clause,Cost,P],
 3151	add_prediction(Tree,Clause,Predict,Examples,Clause1),
 3152	p_message('best clause'),
 3153	pp_dclause(Clause1),
 3154        nlits(Clause,L),
 3155	Gain is -Cost,
 3156        asserta('$aleph_global'(hypothesis,hypothesis([P,0,L,Gain],Clause1,Examples,[]))),
 3157	addhyp,
 3158	fail.
 3159add_tree(_,_,_).
 3160
 3161add_prediction(Tree,Clause,PredictArg,Examples,Clause1):-
 3162	split_clause(Clause,Head,_),
 3163	(Tree = model ->
 3164		setting(evalfn,Evalfn),
 3165		add_model(Evalfn,Clause,PredictArg,Examples,Clause1,_,_);
 3166		node_stats(Tree,Examples,PredictArg,Distribution),
 3167		leaf_prediction(Tree,Distribution,Prediction,Error),
 3168		tparg(PredictArg,Head,Var),
 3169		add_prediction(Tree,Clause,Var,Prediction,Error,Clause1)).
 3170
 3171add_prediction(classification,Clause,Var,Prediction,_,Clause1):-
 3172	extend_clause(Clause,(Var = Prediction),Clause1).
 3173add_prediction(class_probability,Clause,Var,Prediction,_,Clause1):-
 3174	extend_clause(Clause,(random(Var,Prediction)),Clause1).
 3175add_prediction(regression,Clause,Var,Mean,Sd,Clause1):-
 3176	extend_clause(Clause,(random(Var,normal(Mean,Sd))),Clause1).
 3177
 3178add_model(Evalfn,Clause,PredictArg,Examples,_,_,_):-
 3179	retractall('$aleph_local'(tree_model,_,_,_)),
 3180	Best is inf,
 3181	split_clause(Clause,Head,_),
 3182	tparg(PredictArg,Head,Var),
 3183	asserta('$aleph_local'(tree_model,false,0,Best)),
 3184	'$aleph_global'(model,model(Name/Arity)),
 3185	functor(Model,Name,Arity),
 3186	auto_extend(Clause,Model,C),
 3187	leaf_predicts(Arity,Model,Var),
 3188	lazy_evaluate_refinement([],C,[Name/Arity],Examples,[],[],C1),
 3189	find_model_error(Evalfn,Examples,C1,PredictArg,Total,Error),
 3190	'$aleph_local'(tree_model,_,_,BestSoFar),
 3191	(Error < BestSoFar ->
 3192		retract('$aleph_local'(tree_model,_,_,_)),
 3193		asserta('$aleph_local'(tree_model,C1,Total,Error));
 3194		true),
 3195	fail.	
 3196add_model(_,_,_,_,Clause,Total,Error):-
 3197	retract('$aleph_local'(tree_model,Clause,Total,Error)).
 3198
 3199
 3200find_model_error(Evalfn,Examples,(Head:-Body),[PredictArg],T,E):-
 3201	functor(Head,_,Arity),
 3202	findall(Actual-Pred,
 3203			(aleph_member(Interval,Examples),
 3204			aleph_member3(N,Interval),
 3205			example(N,pos,Example),
 3206			copy_iargs(Arity,Example,Head,PredictArg),
 3207			once(Body),
 3208			arg(PredictArg,Head,Pred), 
 3209			arg(PredictArg,Example,Actual)
 3210			), 
 3211		L),
 3212	sum_model_errors(L,Evalfn,0,0.0,T,E), !.
 3213
 3214sum_model_errors([],_,N,E,N,E).
 3215sum_model_errors([Act-Pred|T],Evalfn,NSoFar,ESoFar,N,E):-
 3216	get_model_error(Evalfn,Act,Pred,E1),
 3217	E1SoFar is ESoFar + E1,
 3218	N1SoFar is NSoFar + 1,
 3219	sum_model_errors(T,Evalfn,N1SoFar,E1SoFar,N,E).
 3220
 3221get_model_error(mse,Act,Pred,E):-
 3222	E is (Act-Pred)^2.
 3223get_model_error(accuracy,Act,Pred,E):-
 3224	(Act = Pred -> E is 0.0; E is 1.0).
 3225
 3226leaf_predicts(0,_,_):- !, fail.
 3227leaf_predicts(Arg,Model,Var):-
 3228	arg(Arg,Model,Var1),
 3229	var(Var1),
 3230	Var1 == Var, !.
 3231leaf_predicts(Arg,Model,Var):-
 3232	Arg1 is Arg - 1,
 3233	leaf_predicts(Arg1,Model,Var).
 3234	
 3235leaf_prediction(classification,Total-Distribution,Class,Incorrect):-
 3236	find_maj_class(Distribution,N-Class),
 3237	Incorrect is Total - N.
 3238leaf_prediction(class_probability,T1-D1,NDistr,0):-
 3239	length(D1,NClasses),
 3240	laplace_correct(D1,LaplaceD1),
 3241	LaplaceTotal is T1 + NClasses,
 3242	normalise_distribution(LaplaceD1,LaplaceTotal,NDistr).
 3243leaf_prediction(regression,_-[Mean,Sd],Mean,Sd).
 3244
 3245find_maj_class([X],X):- !.
 3246find_maj_class([N-Class|Rest],MajClass):-
 3247	find_maj_class(Rest,N1-C1),
 3248	(N > N1 -> MajClass = N-Class; MajClass = N1-C1).
 3249
 3250can_split(S,Type,Predict,Leaf,Left,Right):-
 3251	arg(21,S,MinGain),
 3252	'$aleph_search'(tree_leaf,l(Leaf,_,[Clause,Cost,N],Examples)),
 3253	Cost >= MinGain, 
 3254	get_best_subtree(S,Type,Predict,[Clause,Cost,N],Examples,Gain,Left,Right),
 3255	Gain >= MinGain,
 3256	p_message('found clauses'),
 3257	Left = [ClF,CostF|_], Right = [ClS,CostS|_],
 3258	arg(4,S,_/Evalfn),
 3259	pp_dclause(ClS),
 3260	print_eval(Evalfn,CostS),
 3261	pp_dclause(ClF),
 3262	print_eval(Evalfn,CostF),
 3263	p1_message('expected cost reduction'), p_message(Gain).
 3264
 3265get_best_subtree(S,Type,Predict,[Clause,Cost,N],Examples,Gain,Left,Right):-
 3266	arg(42,S,Interactive),
 3267	arg(43,S,LookAhead),
 3268	retractall('$aleph_search'(tree_gain,_)),
 3269	MInf is -inf,
 3270	(Interactive = false ->
 3271		asserta('$aleph_search'(tree_gain,tree_gain(MInf,[],[])));
 3272		true),
 3273	split_clause(Clause,Head,Body),
 3274	arg(4,S,_/Evalfn),
 3275	arg(13,S,MinPos),
 3276	auto_refine(LookAhead,Clause,ClS),
 3277	tree_refine_ok(Type,ClS),
 3278	eval_treenode(S,Type,ClS,Predict,Examples,ExS,NS,CostS),
 3279	NS >= MinPos,
 3280	rm_intervals(ExS,Examples,ExF),
 3281	split_clause(ClS,Head,Body1),
 3282	get_goaldiffs(Body,Body1,Diff),
 3283	extend_clause(Clause,not(Diff),ClF),
 3284	eval_treenode(S,Type,ClF,Predict,ExF,NF,CostF),
 3285	NF >= MinPos,
 3286	AvLeafCost is (NS*CostS + NF*CostF)/N,
 3287	CostReduction is Cost - AvLeafCost,
 3288	(Interactive = false ->
 3289		pp_dclause(ClS), print_eval(Evalfn,CostS),
 3290		pp_dclause(ClF), print_eval(Evalfn,CostF),
 3291		p1_message('expected cost reduction'), p_message(CostReduction),
 3292		'$aleph_search'(tree_gain,tree_gain(BestSoFar,_,_)),
 3293		CostReduction > BestSoFar,
 3294		retract('$aleph_search'(tree_gain,tree_gain(BestSoFar,_,_))),
 3295		asserta('$aleph_search'(tree_gain,tree_gain(CostReduction,
 3296							[ClF,CostF,NF,ExF],
 3297							[ClS,CostS,NS,ExS])));
 3298		asserta('$aleph_search'(tree_gain,tree_gain(CostReduction,
 3299							[ClF,CostF,NF,ExF],
 3300							[ClS,CostS,NS,ExS])))),
 3301
 3302	AvLeafCost =< 0.0, 
 3303	!,
 3304	get_best_subtree(Interactive,Clause,Gain,Left,Right).
 3305get_best_subtree(S,_,_,[Clause|_],_,Gain,Left,Right):-
 3306	arg(42,S,Interactive),
 3307	get_best_subtree(Interactive,Clause,Gain,Left,Right).
 3308
 3309get_best_subtree(false,_,Gain,Left,Right):-
 3310	retract('$aleph_search'(tree_gain,tree_gain(Gain,Left,Right))), !.
 3311get_best_subtree(true,Clause,Gain,Left,Right):-
 3312	nl, write('Extending path: '), nl,
 3313	write('---------------'), nl,
 3314	pp_dclause(Clause),
 3315	findall(MCR-[Left,Right],
 3316		('$aleph_search'(tree_gain,tree_gain(CostReduction,Left,Right)), 
 3317		  MCR is -1*CostReduction), 
 3318		SplitsList),
 3319	keysort(SplitsList,Sorted),
 3320	get_best_split(Clause,Sorted,Gain,Left,Right),
 3321	retractall('$aleph_search'(tree_gain,_)).
 3322
 3323get_best_split(Clause,Splits,Gain,Left,Right):-
 3324	show_split_list(Clause,Splits),
 3325	ask_best_split(Splits,Gain,Left,Right).
 3326
 3327show_split_list(Clause,Splits):-
 3328	tab(4), write('Split Information'), nl,
 3329	tab(4), write('-----------------'), nl, nl,
 3330	tab(4), write('No.'), 
 3331	tab(4), write('Split'), 
 3332	nl,
 3333	tab(4), write('---'), 
 3334	tab(4), write('-----'), 
 3335	nl,
 3336	show_split_list(Splits,1,Clause).
 3337
 3338show_split_list([],_,_).
 3339show_split_list([MCR-[[_,_,NF,_],[CLS,_,NS,_]]|Rest],SplitNum,Clause):-
 3340	copy_term(Clause,ClauseCopy),
 3341	split_clause(ClauseCopy,Head,Body),
 3342	copy_term(CLS,CLSCopy),
 3343	numbervars(CLSCopy,0,_),
 3344	split_clause(CLSCopy,Head,Body1),
 3345	get_goaldiffs(Body,Body1,Diff),
 3346	Gain is -1*MCR,
 3347	tab(4), write(SplitNum),
 3348	tab(4), write(Diff), nl,
 3349	tab(12), write('Succeeded (Right Branch): '), write(NS), nl,
 3350	tab(12), write('Failed    (Left Branch) : '), write(NF), nl,
 3351	tab(12), write('Cost Reduction          : '), write(Gain), nl, nl,
 3352	NextSplit is SplitNum + 1,
 3353	show_split_list(Rest,NextSplit,Clause).
 3354
 3355ask_best_split(Splits,Gain,Left,Right):-
 3356	repeat,
 3357	tab(4), write('-> '),
 3358	write('Select Split Number (or "none.")'), nl,
 3359	read(Answer),
 3360	(Answer = none ->
 3361		Gain is -inf,
 3362		Left = [],
 3363		Right = [];
 3364		SplitNum is integer(Answer),
 3365		aleph_remove_nth(SplitNum,Splits,MCR-[Left,Right],_),
 3366		Gain is -1*MCR
 3367	),
 3368	!.
 3369
 3370tree_refine_ok(model,Clause):-
 3371        '$aleph_global'(model,model(Name/Arity)),
 3372	functor(Model,Name,Arity),
 3373	in(Clause,Model), !,
 3374	fail.
 3375tree_refine_ok(_,_).
 3376
 3377
 3378eval_treenode(S,Tree,Clause,PredictArg,PCov,N,Cost):-
 3379	arg(4,S,_/Evalfn),
 3380	treenode_cost(Tree,Evalfn,Clause,PCov,PredictArg,N,Cost).
 3381
 3382eval_treenode(S,Tree,Clause,PredictArg,Pos,PCov,N,Cost):-
 3383	arg(4,S,_/Evalfn),
 3384	arg(13,S,MinPos),
 3385	arg(14,S,Depth),
 3386	arg(29,S,Time),
 3387	arg(34,S,Proof),
 3388        prove(Depth/Time/Proof,pos,Clause,Pos,PCov,PCount),
 3389	PCount >= MinPos,
 3390	treenode_cost(Tree,Evalfn,Clause,PCov,PredictArg,N,Cost).
 3391
 3392treenode_cost(model,Evalfn,Clause,Covered,PredictArg,Total,Cost):-
 3393	!,
 3394	add_model(Evalfn,Clause,PredictArg,Covered,_,Total,Cost).
 3395treenode_cost(Tree,Evalfn,_,Covered,PredictArg,Total,Cost):-
 3396	node_stats(Tree,Covered,PredictArg,Total-Distribution),
 3397	Total > 0,
 3398	impurity(Tree,Evalfn,Total-Distribution,Cost).
 3399
 3400node_stats(Tree,Covered,PredictArg,D):-
 3401        '$aleph_search'(tree_startdistribution,d(Tree,D0)),
 3402        (Tree = regression ->
 3403                cont_distribution(Covered,PredictArg,D0,D);
 3404                discr_distribution(Covered,PredictArg,D0,D)).
 3405
 3406discr_distribution([],_,D,D).
 3407discr_distribution([S-F|Intervals],PredictArg,T0-D0,D):-
 3408	discr_distribution(S,F,PredictArg,T0-D0,T1-D1),
 3409	discr_distribution(Intervals,PredictArg,T1-D1,D).
 3410
 3411discr_distribution(N,F,_,D,D):- N > F, !.
 3412discr_distribution(N,F,PredictArg,T0-D0,D):-
 3413	example(N,pos,Example),
 3414	tparg(PredictArg,Example,Actual),
 3415	N1 is N + 1,
 3416	T1 is T0 + 1,
 3417	(aleph_delete(C0-Actual,D0,D1) ->
 3418		C1 is C0 + 1,
 3419		discr_distribution(N1,F,PredictArg,T1-[C1-Actual|D1],D);
 3420		discr_distribution(N1,F,PredictArg,T1-[1-Actual|D0],D)).
 3421
 3422cont_distribution([],_,T-[S,SS],T-[Mean,Sd]):-
 3423	(T = 0 -> Mean = 0, Sd = 0;
 3424		Mean is S/T,
 3425		Sd is sqrt(SS/T - Mean*Mean)).
 3426cont_distribution([S-F|Intervals],PredictArg,T0-D0,D):-
 3427        cont_distribution(S,F,PredictArg,T0-D0,T1-D1),
 3428        cont_distribution(Intervals,PredictArg,T1-D1,D).
 3429
 3430cont_distribution(N,F,_,D,D):- N > F, !.
 3431cont_distribution(N,F,PredictArg,T0-[S0,SS0],D):-
 3432        example(N,pos,Example),
 3433        tparg(PredictArg,Example,Actual),
 3434	N1 is N + 1,
 3435        T1 is T0 + 1,
 3436	S1 is S0 + Actual,
 3437	SS1 is SS0 + Actual*Actual,
 3438        cont_distribution(N1,F,PredictArg,T1-[S1,SS1],D).
 3439
 3440impurity(regression,sd,_-[_,Sd],Sd):- !.
 3441impurity(classification,entropy,Total-Distribution,Cost):-
 3442	sum_entropy(Distribution,Total,S),
 3443	Cost is -S/(Total*log(2)), !.
 3444impurity(classification,gini,Total-Distribution,Cost):-
 3445	sum_gini(Distribution,Total,Cost), !.
 3446impurity(class_probability,entropy,Total-Distribution,Cost):-
 3447	sum_entropy(Distribution,Total,S),
 3448	Cost is -S/(Total*log(2)), !.
 3449impurity(class_probability,gini,Total-Distribution,Cost):-
 3450	sum_gini(Distribution,Total,Cost), !.
 3451impurity(_,_,_,_):-
 3452	err_message('inappropriate settings for tree_type and/or evalfn'),
 3453	fail.
 3454
 3455
 3456sum_gini([],_,0).
 3457sum_gini([N-_|Rest],Total,Sum):-
 3458	N > 0, !,
 3459	sum_gini(Rest,Total,C0),
 3460	P is N/Total,
 3461	Sum is P*(1-P) + C0.
 3462sum_gini([_|Rest],Total,Sum):-
 3463	sum_gini(Rest,Total,Sum).
 3464
 3465sum_entropy([],_,0).
 3466sum_entropy([N-_|Rest],Total,Sum):-
 3467	N > 0, !,
 3468	sum_entropy(Rest,Total,C0),
 3469	Sum is N*log(N/Total) + C0.
 3470sum_entropy([_|Rest],Total,Sum):-
 3471	sum_entropy(Rest,Total,Sum).
 3472
 3473% only binary splits
 3474% left = condition at node fails
 3475% right = condition at node succeeds
 3476split_leaf(Leaf,LeftTree,RightTree,[Left,Right]):-
 3477	retract('$aleph_search'(tree_leaf,l(Leaf,Parent,
 3478						[Clause,Cost,N],Examples))),
 3479	gen_leaf(Left),
 3480	gen_leaf(Right),
 3481	LeftTree = [ClF,CostF,NF,ExF],
 3482	RightTree = [ClS,CostS,NS,ExS],
 3483	asserta('$aleph_search'(tree,t(Leaf,Parent,[Clause,Cost,N],
 3484					Examples,Left,Right))),
 3485	asserta('$aleph_search'(tree_leaf,l(Left,Leaf,[ClF,CostF,NF],ExF))),
 3486	asserta('$aleph_search'(tree_leaf,l(Right,Leaf,[ClS,CostS,NS],ExS))).
 3487
 3488gen_leaf(Leaf1):-
 3489	retract('$aleph_search'(tree_lastleaf,Leaf0)), !,
 3490	Leaf1 is Leaf0 + 1,
 3491	asserta('$aleph_search'(tree_lastleaf,Leaf1)).
 3492gen_leaf(0):-
 3493        asserta('$aleph_search'(tree_lastleaf,0)).
 3494
 3495%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 3496% G C W S
 3497
 3498% examine list of clauses to be specialised
 3499% generate an exception theory for each clause that covers negative examples
 3500gcws:-
 3501	setting(evalfn,EvalFn),
 3502	repeat,
 3503	retract('$aleph_search'(sphyp,hypothesis([P,N,L|T],Clause,PCover,NCover))),
 3504	(PCover = _/_ -> label_create(pos,Clause,Label1),
 3505		extract_pos(Label1,PCover1),
 3506		interval_count(PCover1,P1);
 3507		PCover1 = PCover,
 3508		P1 = P),
 3509	(NCover = _/_ -> label_create(neg,Clause,Label2),
 3510		extract_neg(Label2,NCover1),
 3511		interval_count(NCover1,N1);
 3512		NCover1 = NCover,
 3513		N1 = N),
 3514	(N1 = 0 -> NewClause = Clause, NewLabel = [P1,N1,L|T];
 3515		MinAcc is P1/(2*P1 - 1),
 3516		set(minacc,MinAcc),
 3517		set(noise,N1),
 3518		gcws(Clause,PCover1,NCover1,NewClause),
 3519		L1 is L + 1,
 3520		complete_label(EvalFn,NewClause,[P,0,L1],NewLabel)),
 3521	assertz('$aleph_search'(gcwshyp,hypothesis(NewLabel,NewClause,PCover1,[]))),
 3522	\+('$aleph_search'(sphyp,hypothesis(_,_,_,_))), !.
 3523
 3524
 3525% gcws(+Clause,+PCvr,+NCvr,-Clause1)
 3526%	specialise Clause that covers pos examples PCvr and neg examples NCvr
 3527%	result is is Clause extended with a single negated literal
 3528% clauses in exception theory are added to list for specialisation
 3529gcws(Clause,PCover,NCover,Clause1):-
 3530	gen_absym(AbName),
 3531	split_clause(Clause,Head,Body),
 3532	functor(Head,_,Arity),
 3533	add_determinations(AbName/Arity,true),
 3534	add_modes(AbName/Arity),
 3535	gen_ab_examples(AbName/Arity,PCover,NCover),
 3536	cwinduce,
 3537	Head =.. [_|Args],
 3538	AbLit =.. [AbName|Args],
 3539	(Body = true -> Body1 = not(AbLit) ; app_lit(not(AbLit),Body,Body1)),
 3540	Clause1 = (Head:-Body1).
 3541
 3542% greedy set-cover based construction of abnormality theory 
 3543% starts with the first exceptional example
 3544% each clause obtained is added to list of clauses to be specialised 
 3545cwinduce:-
 3546	store(greedy),
 3547        set(greedy,true),
 3548        '$aleph_global'(atoms_left,atoms_left(pos,PosSet)),
 3549        PosSet \= [],
 3550        repeat,
 3551	'$aleph_global'(atoms_left,atoms_left(pos,[Num-X|Y])),
 3552	sat(Num),
 3553	reduce,
 3554	retract('$aleph_global'(hypothesis,hypothesis(Label,H,PCover,NCover))),
 3555	asserta('$aleph_search'(sphyp,hypothesis(Label,H,PCover,NCover))),
 3556        rm_seeds1(PCover,[Num-X|Y],NewPosLeft),
 3557	retract('$aleph_global'(atoms_left,atoms_left(pos,[Num-X|Y]))),
 3558        asserta('$aleph_global'(atoms_left,atoms_left(pos,NewPosLeft))),
 3559	NewPosLeft = [],
 3560        retract('$aleph_global'(atoms_left,atoms_left(pos,NewPosLeft))),
 3561	reinstate(greedy), !.
 3562cwinduce.
 3563
 3564
 3565% gen_ab_examples(+Ab,+PCover,+NCover)
 3566% obtain examples for abnormality predicate Ab by
 3567%	pos examples are copies of neg examples in NCover
 3568%	neg examples are copies of pos examples in PCover
 3569% writes new examples to temporary ".f" and ".n" files
 3570% to ensure example/3 remains a static predicate
 3571% alters search parameters accordingly
 3572gen_ab_examples(Ab/_,PCover,NCover):-
 3573	PosFile = '.alephtmp.f',
 3574	NegFile = '.alephtmp.n',
 3575	create_examples(PosFile,Ab,neg,NCover,pos,PCover1),
 3576	create_examples(NegFile,Ab,pos,PCover,neg,NCover1),
 3577	aleph_consult(PosFile),
 3578	aleph_consult(NegFile),
 3579        retractall('$aleph_global'(atoms_left,_)),
 3580        retractall('$aleph_global'(size,_)),
 3581        asserta('$aleph_global'(atoms_left,atoms_left(pos,PCover1))),
 3582        asserta('$aleph_global'(atoms_left,atoms_left(neg,NCover1))),
 3583        interval_count(PCover1,PSize),
 3584        interval_count(NCover1,NSize),
 3585        asserta('$aleph_global'(size,size(pos,PSize))),
 3586        asserta('$aleph_global'(size,size(neg,NSize))),
 3587	delete_file(PosFile),
 3588	delete_file(NegFile).
 3589
 3590% create_examples(+File,+OldType,+OldE,+NewType,-NewE)
 3591% copy OldE examples of OldType to give NewE examples of NewType 
 3592% copy stored in File
 3593create_examples(File,Ab,OldT,OldE,NewT,[Next-Last]):-
 3594	'$aleph_global'(last_example,last_example(NewT,OldLast)),
 3595	aleph_open(File,write,Stream),
 3596	set_output(Stream),
 3597	create_copy(OldE,OldT,NewT,Ab,OldLast,Last),
 3598	close(Stream),
 3599	set_output(user_output),
 3600	Last > OldLast, !,
 3601	retract('$aleph_global'(last_example,last_example(NewT,OldLast))),
 3602	Next is OldLast + 1,
 3603	asserta('$aleph_global'(last_example,last_example(NewT,Last))).
 3604create_examples(_,_,_,_,_,[]).
 3605
 3606create_copy([],_,_,_,L,L).
 3607create_copy([X-Y|T],OldT,NewT,Ab,Num,Last):-
 3608	create_copy(X,Y,OldT,NewT,Ab,Num,Num1),
 3609	create_copy(T,OldT,NewT,Ab,Num1,Last).
 3610
 3611create_copy(X,Y,_,_,_,L,L):- X > Y, !.
 3612create_copy(X,Y,OldT,NewT,Ab,Num,Last):-
 3613	example(X,OldT,Example),
 3614	Example =.. [_|Args],
 3615	NewExample =.. [Ab|Args],
 3616	Num1 is Num + 1,
 3617	aleph_writeq(example(Num1,NewT,NewExample)), write('.'), nl,
 3618	X1 is X + 1,
 3619	create_copy(X1,Y,OldT,NewT,Ab,Num1,Last).
 3620
 3621% gen_absym(-Name)
 3622% generate new abnormality predicate symbol
 3623gen_absym(Name):-
 3624	(retract('$aleph_global'(last_ab,last_ab(N))) ->
 3625		N1 is N + 1;
 3626		N1 is 0),
 3627	asserta('$aleph_global'(last_ab,last_ab(N1))),
 3628	concat([ab,N1],Name).
 3629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 3630% C L A U S E   O P T I M I S A T I O N S
 3631
 3632
 3633optimise(Clause,Clause1):-
 3634	remove_redundant(Clause,Clause0),
 3635	reorder_clause(Clause0,Clause1).
 3636
 3637remove_redundant((Head:-Body),(Head1:-Body1)):-
 3638	goals_to_list((Head,Body),ClauseL),
 3639	remove_subsumed(ClauseL,[Head1|Body1L]),
 3640	(Body1L = [] -> Body1 = true; list_to_goals(Body1L,Body1)).
 3641
 3642reorder_clause((Head:-Body), Clause) :-
 3643        % term_variables(Head,LHead),
 3644        vars_in_term([Head],[],LHead),
 3645        number_goals_and_get_vars(Body,LHead,1,_,[],Conj),
 3646        calculate_independent_sets(Conj,[],BSets),
 3647        compile_clause(BSets,Head,Clause).
 3648
 3649number_goals_and_get_vars((G,Body),LHead,I0,IF,L0,[g(I0,LVF,NG)|LGs]) :- !,
 3650        I is I0+1,
 3651        get_goal_vars(G,LHead,LVF,NG),
 3652        number_goals_and_get_vars(Body,LHead,I,IF,L0,LGs).
 3653number_goals_and_get_vars(G,LHead,I,I,L0,[g(I,LVF,NG)|L0]) :-
 3654        get_goal_vars(G,LHead,LVF,NG).
 3655
 3656get_goal_vars(G,LHead,LVF,G) :-
 3657        % term_variables(G,LV0),
 3658        vars_in_term([G],[],LVI),
 3659        aleph_ord_subtract(LVI,LHead,LVF).
 3660
 3661calculate_independent_sets([],BSets,BSets).
 3662calculate_independent_sets([G|Ls],BSets0,BSetsF) :-
 3663        add_goal_to_set(G,BSets0,BSetsI),
 3664        calculate_independent_sets(Ls,BSetsI,BSetsF).
 3665
 3666add_goal_to_set(g(I,LV,G),Sets0,SetsF) :-
 3667        add_to_sets(Sets0,LV,[g(I,LV,G)],SetsF).
 3668
 3669add_to_sets([],LV,Gs,[[LV|Gs]]).
 3670add_to_sets([[LV|Gs]|Sets0],LVC,GsC,[[LV|Gs]|SetsF]) :-
 3671        aleph_ord_disjoint(LV,LVC), !,
 3672        add_to_sets(Sets0,LVC,GsC,SetsF).
 3673add_to_sets([[LV|Gs]|Sets0],LVC,GsC,SetsF) :-
 3674        aleph_ord_union(LV,LVC,LVN),
 3675        join_goals(Gs,GsC,GsN),
 3676        add_to_sets(Sets0,LVN,GsN,SetsF).
 3677
 3678join_goals([],L,L):- !.
 3679join_goals(L,[],L):- !.
 3680join_goals([g(I1,VL1,G1)|T],[g(I2,VL2,G2)|T2],Z) :-
 3681        I1 < I2, !,
 3682        Z = [g(I1,VL1,G1)|TN],
 3683        join_goals(T,[g(I2,VL2,G2)|T2],TN).
 3684join_goals([H|T],[g(I2,VL2,G2)|T2],Z) :-
 3685        Z = [g(I2,VL2,G2)|TN],
 3686        join_goals(T,[H|T2],TN).
 3687
 3688compile_clause(Goals,Head,(Head:-Body)):-
 3689        compile_clause2(Goals,Body).
 3690
 3691compile_clause2([[_|B]], B1):-
 3692	!,
 3693        glist_to_goals(B,B1).
 3694compile_clause2([[_|B]|Bs],(B1,!,NB)):-
 3695        glist_to_goals(B,B1),
 3696        compile_clause2(Bs,NB).
 3697
 3698glist_to_goals([g(_,_,Goal)],Goal):- !.
 3699glist_to_goals([g(_,_,Goal)|Goals],(Goal,Goals1)):-
 3700        glist_to_goals(Goals,Goals1).
 3701
 3702% remove literals subsumed in the body of a clause
 3703remove_subsumed([Head|Lits],Lits1):-
 3704	delete(Lit,Lits,Left),
 3705	\+(\+(redundant(Lit,[Head|Lits],[Head|Left]))), !,
 3706	remove_subsumed([Head|Left],Lits1).
 3707remove_subsumed(L,L).
 3708
 3709% determine if Lit is subsumed by a body literal
 3710redundant(Lit,Lits,[Head|Body]):-
 3711	copy_term([Head|Body],Rest1),
 3712	member(Lit1,Body),
 3713	Lit = Lit1,
 3714	aleph_subsumes(Lits,Rest1).
 3715
 3716aleph_subsumes(Lits,Lits1):-
 3717	\+(\+((numbervars(Lits,0,_),numbervars(Lits1,0,_),aleph_subset1(Lits,Lits1)))).
 3718
 3719
 3720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 3721% S A T  /  R E D U C E
 3722
 3723sat(Num):-
 3724	integer(Num),
 3725	example(Num,pos,_),
 3726	sat(pos,Num), !.
 3727sat(Example):-
 3728	record_example(check,uspec,Example,Num),
 3729	sat(uspec,Num), !.
 3730
 3731sat(Type,Num):-
 3732        setting(construct_bottom,false), !,
 3733        sat_prelims,
 3734	example(Num,Type,Example),
 3735	broadcast(start(sat(Num))),
 3736	p1_message('sat'), p_message(Num), p_message(Example),
 3737	record_sat_example(Num),
 3738	asserta('$aleph_sat'(example,example(Num,Type))),
 3739	asserta('$aleph_sat'(hovars,[])),
 3740	broadcast(end(sat(Num, 0, 0.0))).
 3741sat(Type,Num):-
 3742	setting(construct_bottom,reduction), !,
 3743	sat_prelims,
 3744	example(Num,Type,Example),
 3745	broadcast(start(sat(Num))),
 3746	p1_message('sat'), p_message(Num), p_message(Example),
 3747	record_sat_example(Num),
 3748	asserta('$aleph_sat'(example,example(Num,Type))),
 3749	integrate_head_lit(HeadOVars),
 3750	asserta('$aleph_sat'(hovars,HeadOVars)),
 3751	broadcast(end(sat(Num, 0, 0.0))).
 3752sat(Type,Num):-
 3753	set(stage,saturation),
 3754	sat_prelims,
 3755	example(Num,Type,Example),
 3756	broadcast(start(sat(Num))),
 3757	p1_message('sat'), p_message(Num), p_message(Example),
 3758	record_sat_example(Num),
 3759	asserta('$aleph_sat'(example,example(Num,Type))),
 3760	split_args(Example,Mode,Input,Output,Constants),
 3761	integrate_args(unknown,Example,Output),
 3762	stopwatch(StartClock),
 3763	assertz('$aleph_sat_atom'(Example,mode(Mode,Output,Input,Constants))),
 3764	'$aleph_global'(i,set(i,Ival)),
 3765	flatten(0,Ival,0,Last1),
 3766	'$aleph_sat_litinfo'(1,_,Atom,_,_,_),
 3767	get_vars(Atom,Output,HeadOVars),
 3768	asserta('$aleph_sat'(hovars,HeadOVars)),
 3769	get_vars(Atom,Input,HeadIVars),
 3770	asserta('$aleph_sat'(hivars,HeadIVars)),
 3771	functor(Example,Name,Arity), 
 3772	get_determs(Name/Arity,L),
 3773	('$aleph_global'(determination,determination(Name/Arity,'='/2))->
 3774		asserta('$aleph_sat'(eq,true));
 3775		asserta('$aleph_sat'(eq,false))),
 3776	get_atoms(L,1,Ival,Last1,Last),
 3777	stopwatch(StopClock),
 3778	Time is StopClock - StartClock,
 3779	asserta('$aleph_sat'(lastlit,Last)),
 3780	asserta('$aleph_sat'(botsize,Last)),
 3781	update_generators,
 3782	rm_moderepeats(Last,Repeats),
 3783	rm_commutative(Last,Commutative),
 3784	rm_symmetric(Last,Symmetric),
 3785	rm_redundant(Last,Redundant),
 3786	rm_uselesslits(Last,NotConnected),
 3787	rm_nreduce(Last,NegReduced),
 3788	TotalLiterals is
 3789		Last-Repeats-NotConnected-Commutative-Symmetric-Redundant-NegReduced,
 3790	show(bottom),
 3791	p1_message('literals'), p_message(TotalLiterals),
 3792	p1_message('saturation time'), p_message(Time),
 3793	broadcast(end(sat(Num, TotalLiterals, Time))),
 3794	store(bottom),
 3795	noset(stage).
 3796sat(_,_):-
 3797	noset(stage).
 3798
 3799reduce:-
 3800	setting(search,Search), 
 3801	catch(reduce(Search),abort,reinstate_values), !.
 3802
 3803% no search: add bottom clause as hypothesis
 3804reduce(false):-
 3805	!,
 3806	add_bottom.
 3807% iterative beam search as described by Ross Quinlan+MikeCameron-Jones,IJCAI-95
 3808reduce(ibs):-
 3809	!,
 3810	retractall('$aleph_search'(ibs_rval,_)),
 3811	retractall('$aleph_search'(ibs_nodes,_)),
 3812	retractall('$aleph_search'(ibs_selected,_)),
 3813	store_values([openlist,caching,explore]),
 3814	set(openlist,1),
 3815	set(caching,true),
 3816	set(explore,true),
 3817	asserta('$aleph_search'(ibs_rval,1.0)),
 3818	asserta('$aleph_search'(ibs_nodes,0)),
 3819	setting(evalfn,Evalfn),
 3820	get_start_label(Evalfn,Label),
 3821	('$aleph_sat'(example,example(Num,Type)) ->
 3822		example(Num,Type,Example),
 3823		asserta('$aleph_search'(ibs_selected,selected(Label,(Example:-true),
 3824				[Num-Num],[])));
 3825		asserta('$aleph_search'(ibs_selected,selected(Label,(false:-true),
 3826				[],[])))),
 3827	stopwatch(Start),
 3828	repeat,
 3829	setting(openlist,OldOpen),
 3830	p1_message('ibs beam width'), p_message(OldOpen),
 3831	find_clause(bf),
 3832	'$aleph_search'(current,current(_,Nodes0,[PC,NC|_]/_)),
 3833	N is NC + PC,
 3834	estimate_error_rate(Nodes0,0.5,N,NC,NewR),
 3835	p1_message('ibs estimated error'), p_message(NewR),
 3836	retract('$aleph_search'(ibs_rval,OldR)),
 3837	retract('$aleph_search'(ibs_nodes,Nodes1)),
 3838        '$aleph_search'(selected,selected(BL,RCl,PCov,NCov)),
 3839	NewOpen is 2*OldOpen,
 3840	Nodes2 is Nodes0 + Nodes1,
 3841	set(openlist,NewOpen),
 3842	asserta('$aleph_search'(ibs_rval,NewR)),
 3843	asserta('$aleph_search'(ibs_nodes,Nodes2)),
 3844	((NewR >= OldR; NewOpen > 512) -> true;
 3845		retract('$aleph_search'(ibs_selected,selected(_,_,_,_))),
 3846		asserta('$aleph_search'(ibs_selected,selected(BL,RCl,PCov,NCov))),
 3847		fail),
 3848	!,
 3849	stopwatch(Stop),
 3850	Time is Stop - Start,
 3851	retractall('$aleph_search'(ibs_rval,_)),
 3852	retract('$aleph_search'(ibs_nodes,Nodes)),
 3853        retract('$aleph_search'(ibs_selected,selected(BestLabel,RClause,PCover,NCover))),
 3854	add_hyp(BestLabel,RClause,PCover,NCover),
 3855	p1_message('ibs clauses constructed'), p_message(Nodes),
 3856	p1_message('ibs search time'), p_message(Time),
 3857	p_message('ibs best clause'),
 3858	pp_dclause(RClause),
 3859	show_stats(Evalfn,BestLabel),
 3860	record_search_stats(RClause,Nodes,Time),
 3861	reinstate_values([openlist,caching,explore]).
 3862
 3863% iterative deepening search
 3864reduce(id):-
 3865	!,
 3866	retractall('$aleph_search'(id_nodes,_)),
 3867	retractall('$aleph_search'(id_selected,_)),
 3868	store_values([caching,clauselength]),
 3869	setting(clauselength,MaxCLen),
 3870	set(clauselength,1),
 3871	set(caching,true),
 3872	asserta('$aleph_search'(id_nodes,0)),
 3873	setting(evalfn,Evalfn),
 3874	get_start_label(Evalfn,Label),
 3875	('$aleph_sat'(example,example(Num,Type)) ->
 3876		example(Num,Type,Example),
 3877		asserta('$aleph_search'(id_selected,selected(Label,(Example:-true),
 3878				[Num-Num],[])));
 3879		asserta('$aleph_search'(id_selected,selected(Label,(false:-true),
 3880				[],[])))),
 3881	stopwatch(Start),
 3882	repeat,
 3883	setting(clauselength,OldCLen),
 3884	p1_message('id clauselength setting'), p_message(OldCLen),
 3885	find_clause(df),
 3886	'$aleph_search'(current,current(_,Nodes0,_)),
 3887	retract('$aleph_search'(id_nodes,Nodes1)),
 3888        '$aleph_search'(selected,selected([P,N,L,F|T],RCl,PCov,NCov)),
 3889	'$aleph_search'(id_selected,selected([_,_,_,F1|_],_,_,_)),
 3890	NewCLen is OldCLen + 1,
 3891	Nodes2 is Nodes0 + Nodes1,
 3892	set(clauselength,NewCLen),
 3893	'$aleph_search'(id_nodes,Nodes2),
 3894	(F1 >= F -> true;
 3895		retract('$aleph_search'(id_selected,selected([_,_,_,F1|_],_,_,_))),
 3896		asserta('$aleph_search'(id_selected,selected([P,N,L,F|T],RCl,PCov,NCov))),
 3897		set(best,[P,N,L,F|T])),
 3898	NewCLen > MaxCLen,
 3899	!,
 3900	stopwatch(Stop),
 3901	Time is Stop - Start,
 3902	retract('$aleph_search'(id_nodes,Nodes)),
 3903        retract('$aleph_search'(id_selected,selected(BestLabel,RClause,PCover,NCover))),
 3904	add_hyp(BestLabel,RClause,PCover,NCover),
 3905	p1_message('id clauses constructed'), p_message(Nodes),
 3906	p1_message('id search time'), p_message(Time),
 3907	p_message('id best clause'),
 3908	pp_dclause(RClause),
 3909	show_stats(Evalfn,BestLabel),
 3910	record_search_stats(RClause,Nodes,Time),
 3911	noset(best),
 3912	reinstate_values([caching,clauselength]).
 3913
 3914% iterative language search as described by Rui Camacho, 1996
 3915reduce(ils):-
 3916	!,
 3917	retractall('$aleph_search'(ils_nodes,_)),
 3918	retractall('$aleph_search'(ils_selected,_)), 
 3919	store_values([caching,language]),
 3920	set(searchstrat,bf),
 3921	set(language,1),
 3922	set(caching,true),
 3923	asserta('$aleph_search'(ils_nodes,0)),
 3924	setting(evalfn,Evalfn),
 3925	get_start_label(Evalfn,Label),
 3926	('$aleph_sat'(example,example(Num,Type)) ->
 3927		example(Num,Type,Example),
 3928		asserta('$aleph_search'(ils_selected,selected(Label,(Example:-true),
 3929				[Num-Num],[])));
 3930		asserta('$aleph_search'(ils_selected,selected(Label,(false:-true),
 3931				[],[])))),
 3932	stopwatch(Start),
 3933	repeat,
 3934	setting(language,OldLang),
 3935	p1_message('ils language setting'), p_message(OldLang),
 3936	find_clause(bf),
 3937	'$aleph_search'(current,current(_,Nodes0,_)),
 3938	retract('$aleph_search'(ils_nodes,Nodes1)),
 3939        '$aleph_search'(selected,selected([P,N,L,F|T],RCl,PCov,NCov)),
 3940	'$aleph_search'(ils_selected,selected([_,_,_,F1|_],_,_,_)),
 3941	NewLang is OldLang + 1,
 3942	Nodes2 is Nodes0 + Nodes1,
 3943	set(language,NewLang),
 3944	asserta('$aleph_search'(ils_nodes,Nodes2)),
 3945	(F1 >= F -> true;
 3946		retract('$aleph_search'(ils_selected,selected([_,_,_,F1|_],_,_,_))),
 3947		asserta('$aleph_search'(ils_selected,selected([P,N,L,F|T],RCl,PCov,NCov))),
 3948		set(best,[P,N,L,F|T]),
 3949		fail),
 3950	!,
 3951	stopwatch(Stop),
 3952	Time is Stop - Start,
 3953	retract('$aleph_search'(ils_nodes,Nodes)),
 3954        retract('$aleph_search'(ils_selected,selected(BestLabel,RClause,PCover,NCover))),
 3955	add_hyp(BestLabel,RClause,PCover,NCover),
 3956	p1_message('ils clauses constructed'), p_message(Nodes),
 3957	p1_message('ils search time'), p_message(Time),
 3958	p_message('ils best clause'),
 3959	pp_dclause(RClause),
 3960	show_stats(Evalfn,BestLabel),
 3961	record_search_stats(RClause,Nodes,Time),
 3962	noset(best),
 3963	reinstate_values([caching,language]).
 3964
 3965
 3966% implementation of a randomised local search for clauses
 3967% currently, this can use either: simulated annealing with a fixed temp
 3968% or a GSAT-like algorithm
 3969% the choice of these is specified by the parameter: rls_type
 3970% both annealing and GSAT employ random multiple restarts
 3971% and a limit on the number of moves
 3972%	the number of restarts is specified by set(tries,...)
 3973%	the number of moves is specified by set(moves,...)
 3974% annealing currently restricted to using a fixed temperature
 3975%	the temperature is specified by set(temperature,...)
 3976%	the use of a fixed temp. makes it equivalent to the Metropolis alg.
 3977% GSAT if given a ``random-walk probability'' performs Selman et als walksat
 3978%	the walk probability is specified by set(walk,...)
 3979%	a walk probability of 0 is equivalent to doing standard GSAT
 3980reduce(rls):-
 3981	!,
 3982	setting(tries,MaxTries),
 3983	MaxTries >= 1,
 3984	store_values([caching,refine,refineop]),
 3985	set(searchstrat,heuristic),
 3986	set(caching,true),
 3987	setting(refine,Refine),
 3988	(Refine \= false  -> true; set(refineop,rls)),
 3989	setting(threads,Threads),
 3990	rls_search(Threads, MaxTries, Time, Nodes, selected(BestLabel,
 3991					RBest,PCover,NCover)),
 3992	add_hyp(BestLabel,RBest,PCover,NCover),
 3993	p1_message('rls nodes constructed'), p_message(Nodes),
 3994	p1_message('rls search time'), p_message(Time),
 3995	p_message('rls best result'),
 3996	pp_dclause(RBest),
 3997	setting(evalfn,Evalfn),
 3998	show_stats(Evalfn,BestLabel),
 3999	record_search_stats(RBest,Nodes,Time),
 4000	noset(best),
 4001	reinstate_values([caching,refine,refineop]).
 4002
 4003
 4004% stochastic clause selection based on ordinal optimisation
 4005% see papers by Y.C. Ho and colleagues for more details
 4006reduce(scs):-
 4007	!,
 4008	store_values([tries,moves,rls_type,clauselength_distribution]),
 4009	stopwatch(Start),
 4010	(setting(scs_sample,SampleSize) -> true;
 4011		setting(scs_percentile,K),
 4012		K > 0.0,
 4013		setting(scs_prob,P),
 4014		P < 1.0,
 4015		SampleSize is integer(log(1-P)/log(1-K/100) + 1)),
 4016	(setting(scs_type,informed)->
 4017		(setting(clauselength_distribution,_D) -> true;
 4018			setting(clauselength,CL),
 4019			estimate_clauselength_distribution(CL,100,K,D),
 4020			% max_in_list(D,Prob-Length),
 4021			% p1_message('using clauselength distribution'),
 4022			% p_message([Prob-Length]),
 4023			% set(clauselength_distribution,[Prob-Length]));
 4024			p1_message('using clauselength distribution'),
 4025			p_message(D),
 4026			set(clauselength_distribution,D));
 4027		true),
 4028	set(tries,SampleSize),
 4029	set(moves,0),
 4030	set(rls_type,gsat),
 4031	reduce(rls),
 4032	stopwatch(Stop),
 4033	Time is Stop - Start,
 4034	'$aleph_search'(rls_nodes,Nodes),
 4035        '$aleph_search'(rls_selected,selected(BestLabel,RBest,_,_)),
 4036	p1_message('scs nodes constructed'), p_message(Nodes),
 4037	p1_message('scs search time'), p_message(Time),
 4038	p_message('scs best result'),
 4039	pp_dclause(RBest),
 4040	setting(evalfn,Evalfn),
 4041	show_stats(Evalfn,BestLabel),
 4042	record_search_stats(RBest,Nodes,Time),
 4043	p1_message('scs search time'), p_message(Time),
 4044	reinstate_values([tries,moves,rls_type,clauselength_distribution]).
 4045
 4046% simple association rule search
 4047% For a much more sophisticated approach see: L. Dehaspe, PhD Thesis, 1998
 4048% Here, simply find all rules within search that cover at least
 4049% a pre-specificed fraction of the positive examples
 4050reduce(ar):-
 4051	!,
 4052	clear_cache,
 4053	(setting(pos_fraction,PFrac) -> true;
 4054		p_message('value required for pos_fraction parameter'),
 4055		fail),
 4056        '$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 4057	retract('$aleph_global'(atoms_left,atoms_left(neg,Neg))),
 4058	interval_count(Pos,P),
 4059	MinPos is PFrac*P,
 4060	store_values([minpos,evalfn,explore,caching,minacc,good]),
 4061	set(searchstrat,bf),
 4062	set(minpos,MinPos),
 4063	set(evalfn,coverage),
 4064	set(explore,true),
 4065	set(caching,true),
 4066	set(minacc,0.0),
 4067	set(good,true),
 4068	asserta('$aleph_global'(atoms_left,atoms_left(neg,[]))),
 4069	find_clause(bf),
 4070	show(good),
 4071	retract('$aleph_global'(atoms_left,atoms_left(neg,[]))),
 4072	asserta('$aleph_global'(atoms_left,atoms_left(neg,Neg))),
 4073	reinstate_values([minpos,evalfn,explore,caching,minacc,good]).
 4074
 4075% search for integrity constraints
 4076% modelled on the work by L. De Raedt and L. Dehaspe, 1996
 4077reduce(ic):-
 4078	!,
 4079	store_values([minpos,minscore,evalfn,explore,refineop]),
 4080	setting(refineop,RefineOp),
 4081	(RefineOp = false -> set(refineop,auto); true),
 4082	set(minpos,0),
 4083	set(searchstrat,bf),
 4084	set(evalfn,coverage),
 4085	set(explore,true),
 4086	setting(noise,N),
 4087	MinScore is -N,
 4088	set(minscore,MinScore),
 4089	find_clause(bf),
 4090	reinstate_values([minpos,minscore,evalfn,explore,refineop]).
 4091
 4092reduce(bf):-
 4093	!,
 4094	find_clause(bf).
 4095
 4096reduce(df):-
 4097	!,
 4098	find_clause(df).
 4099
 4100reduce(heuristic):-
 4101	!,
 4102	find_clause(heuristic).
 4103
 4104
 4105% find_clause(Search) where Search is one of bf, df, heuristic
 4106find_clause(Search):-
 4107	set(stage,reduction),
 4108	set(searchstrat,Search),
 4109	p_message('reduce'),
 4110	reduce_prelims(L,P,N),
 4111	asserta('$aleph_search'(openlist,[])),
 4112	get_search_settings(S),
 4113	arg(4,S,_/Evalfn),
 4114	get_start_label(Evalfn,Label),
 4115	('$aleph_sat'(example,example(Num,Type)) ->
 4116		example(Num,Type,Example),
 4117		asserta('$aleph_search'(selected,selected(Label,(Example:-true),
 4118							[Num-Num],[])));
 4119		asserta('$aleph_search'(selected,selected(Label,(false:-true),[],[])))),
 4120	arg(13,S,MinPos),
 4121	interval_count(P,PosLeft),
 4122	PosLeft >= MinPos,
 4123	'$aleph_search'(selected,selected(L0,C0,P0,N0)),
 4124	add_hyp(L0,C0,P0,N0),
 4125        ('$aleph_global'(max_set,max_set(Type,Num,Label1,ClauseNum))->
 4126		BestSoFar = Label1/ClauseNum;
 4127		('$aleph_global'(best,set(best,Label2))->
 4128			BestSoFar = Label2/0;
 4129			BestSoFar = Label/0)),
 4130        asserta('$aleph_search'(best_label,BestSoFar)),
 4131	p1_message('best label so far'), p_message(BestSoFar),
 4132        arg(3,S,RefineOp),
 4133	stopwatch(StartClock),
 4134        (RefineOp = false ->
 4135                get_gains(S,0,BestSoFar,[],false,[],0,L,[1],P,N,[],1,Last,NextBest),
 4136		update_max_head_count(0,Last);
 4137		clear_cache,
 4138		interval_count(P,MaxPC),
 4139		asserta('$aleph_local'(max_head_count,MaxPC)),
 4140		StartClause = 0-[Num,Type,[],false],
 4141                get_gains(S,0,BestSoFar,StartClause,_,_,_,L,[StartClause],
 4142				P,N,[],1,Last,NextBest)),
 4143        asserta('$aleph_search_expansion'(1,0,1,Last)),
 4144	get_nextbest(S,_),
 4145	asserta('$aleph_search'(current,current(1,Last,NextBest))),
 4146	search(S,Nodes),
 4147	stopwatch(StopClock),
 4148	Time is StopClock - StartClock,
 4149        '$aleph_search'(selected,selected(BestLabel,RClause,PCover,NCover)),
 4150	retract('$aleph_search'(openlist,_)),
 4151	add_hyp(BestLabel,RClause,PCover,NCover),
 4152	p1_message('clauses constructed'), p_message(Nodes),
 4153	p1_message('search time'), p_message(Time),
 4154	p_message('best clause'),
 4155	pp_dclause(RClause),
 4156	show_stats(Evalfn,BestLabel),
 4157	update_search_stats(Nodes,Time),
 4158	record_search_stats(RClause,Nodes,Time),
 4159	noset(stage),
 4160	!.
 4161find_clause(_):-
 4162        '$aleph_search'(selected,selected(BestLabel,RClause,PCover,NCover)),
 4163	retract('$aleph_search'(openlist,_)),
 4164	add_hyp(BestLabel,RClause,PCover,NCover),
 4165	p_message('best clause'),
 4166	pp_dclause(RClause),
 4167	(setting(evalfn,Evalfn) -> true; Evalfn = coverage),
 4168	show_stats(Evalfn,BestLabel),
 4169	noset(stage),
 4170	!.
 4171
 4172% find_theory(Search) where Search is rls only at present
 4173find_theory(rls):-
 4174	!,
 4175	retractall('$aleph_search'(rls_move,_)),
 4176	retractall('$aleph_search'(rls_nodes,_)),
 4177	retractall('$aleph_search'(rls_parentstats,_)),
 4178	retractall('$aleph_search'(rls_selected,_)),
 4179	setting(tries,MaxTries),
 4180	MaxTries >= 1,
 4181	store_values([caching,store_bottom]),
 4182	set(caching,false),
 4183	set(store_bottom,true),
 4184        '$aleph_global'(atoms,atoms(pos,PosSet)),
 4185        '$aleph_global'(atoms,atoms(neg,NegSet)),
 4186        interval_count(PosSet,P0),
 4187        interval_count(NegSet,N0),
 4188	setting(evalfn,Evalfn),
 4189        complete_label(Evalfn,[0-[0,0,[],false]],[P0,N0,1],Label),
 4190	asserta('$aleph_search'(rls_selected,selected(Label,[0-[0,0,[],false]],
 4191						PosSet,NegSet))),
 4192	asserta('$aleph_search'(rls_nodes,0)),
 4193	asserta('$aleph_search'(rls_restart,1)),
 4194	get_search_settings(S),
 4195	set(best,Label),
 4196	stopwatch(Start),
 4197	repeat,
 4198	retractall('$aleph_search'(rls_parentstats,_)),
 4199	retractall('$aleph_search'(rls_move,_)),
 4200	retractall('$aleph_search_seen'(_,_)),
 4201	asserta('$aleph_search'(rls_move,1)),
 4202	asserta('$aleph_search'(rls_parentstats,stats(Label,PosSet,NegSet))),
 4203	'$aleph_search'(rls_restart,R),
 4204	p1_message('restart'), p_message(R),
 4205	find_theory1(rls),
 4206	'$aleph_search'(current,current(_,Nodes0,_)),
 4207	retract('$aleph_search'(rls_nodes,Nodes1)),
 4208        '$aleph_search'(selected,selected([P,N,L,F|T],RCl,PCov,NCov)),
 4209	'$aleph_search'(rls_selected,selected([_,_,_,F1|_],_,_,_)),
 4210	retract('$aleph_search'(rls_restart,R)),
 4211	R1 is R + 1,
 4212	asserta('$aleph_search'(rls_restart,R1)),
 4213	Nodes2 is Nodes0 + Nodes1,
 4214	asserta('$aleph_search'(rls_nodes,Nodes2)),
 4215	(F1 >= F -> true;
 4216		retract('$aleph_search'(rls_selected,selected([_,_,_,F1|_],_,_,_))),
 4217		asserta('$aleph_search'(rls_selected,selected([P,N,L,F|T],RCl,PCov,NCov))),
 4218		set(best,[P,N,L,F|T])),
 4219	setting(best,BestSoFar),
 4220	(R1 > MaxTries;discontinue_search(S,BestSoFar/_,Nodes2)),
 4221	!,
 4222	stopwatch(Stop),
 4223	Time is Stop - Start,
 4224	'$aleph_search'(rls_nodes,Nodes),
 4225        '$aleph_search'(rls_selected,selected(BestLabel,RBest,PCover,NCover)),
 4226	add_hyp(BestLabel,RBest,PCover,NCover),
 4227	p1_message('nodes constructed'), p_message(Nodes),
 4228	p1_message('search time'), p_message(Time),
 4229	p_message('best theory'),
 4230	pp_dclauses(RBest),
 4231	show_stats(Evalfn,BestLabel),
 4232	record_search_stats(RBest,Nodes,Time),
 4233	noset(best),
 4234	reinstate_values([caching,refine,refineop,store_bottom]).
 4235
 4236find_theory1(_):-
 4237	clean_up_reduce,
 4238        '$aleph_global'(atoms,atoms(pos,Pos)),
 4239        '$aleph_global'(atoms,atoms(neg,Neg)),
 4240        asserta('$aleph_search'(openlist,[])),
 4241	asserta('$aleph_search'(nextnode,none)),
 4242        stopwatch(StartClock),
 4243        get_search_settings(S),
 4244	arg(4,S,_/Evalfn),
 4245        interval_count(Pos,P),
 4246        interval_count(Neg,N),
 4247        complete_label(Evalfn,[0-[0,0,[],false]],[P,N,1],Label),
 4248	asserta('$aleph_search'(selected,selected(Label,[0-[0,0,[],false]],Pos,Neg))),
 4249	get_theory_gain(S,0,Label/0,[0-[0,0,[],false]],Pos,Neg,P,N,NextBest,Last),
 4250	asserta('$aleph_search'(current,current(0,Last,NextBest))),
 4251	get_nextbest(S,_),
 4252	tsearch(S,Nodes),
 4253	stopwatch(StopClock),
 4254	Time is StopClock - StartClock,
 4255	'$aleph_search'(selected,selected(BestLabel,RTheory,PCover,NCover)),
 4256	retract('$aleph_search'(openlist,_)),
 4257	add_hyp(BestLabel,RTheory,PCover,NCover),
 4258	p1_message('theories constructed'), p_message(Nodes),
 4259	p1_message('search time'), p_message(Time),
 4260	p_message('best theory'),
 4261	pp_dclauses(RTheory),
 4262	show_stats(Evalfn,BestLabel),
 4263	update_search_stats(Nodes,Time),
 4264	record_tsearch_stats(RTheory,Nodes,Time).
 4265
 4266estimate_error_rate(H,Del,N,E,R):-
 4267	TargetProb is 1-exp(log(1-Del)/H),
 4268	estimate_error(1.0/0.0,0.0/1.0,TargetProb,N,E,R).
 4269
 4270estimate_error(L/P1,U/P2,P,N,E,R):-
 4271	M is (L+U)/2,
 4272	binom_lte(N,M,E,P3),
 4273	ADiff is abs(P - P3),
 4274	(ADiff < 0.00001 ->
 4275		R is M;
 4276		(P3 > P ->
 4277			estimate_error(L/P1,M/P3,P,N,E,R);
 4278			estimate_error(M/P3,U/P2,P,N,E,R)
 4279		)
 4280	).
 4281		
 4282
 4283zap_rest(Lits):-
 4284	retract('$aleph_sat_litinfo'(LitNum,Depth,Atom,I,O,D)),
 4285	(aleph_member1(LitNum,Lits) ->
 4286		intersect1(Lits,D,D1,_),
 4287		asserta('$aleph_sat_litinfo'(LitNum,Depth,Atom,I,O,D1));
 4288		true),
 4289	fail.
 4290zap_rest(_).
 4291
 4292sat_prelims:-
 4293	clean_up_sat,
 4294	clean_up_hypothesis,
 4295	reset_counts,
 4296	set_up_builtins.
 4297	
 4298
 4299reduce_prelims(L,P,N):-
 4300	clean_up_reduce,
 4301	check_posonly,
 4302	check_auto_refine,
 4303	('$aleph_sat'(lastlit,L) -> true;
 4304		L = 0, asserta('$aleph_sat'(lastlit,L))),
 4305	('$aleph_sat'(botsize,_B) -> true;
 4306		B = 0, asserta('$aleph_sat'(botsize,B))),
 4307        (('$aleph_global'(lazy_evaluate,lazy_evaluate(_));setting(greedy,true))->
 4308                '$aleph_global'(atoms_left,atoms_left(pos,P));
 4309                '$aleph_global'(atoms,atoms(pos,P))),
 4310	setting(evalfn,E),
 4311	(E = posonly -> NType = rand; NType = neg),
 4312	'$aleph_global'(atoms_left,atoms_left(NType,N)),
 4313	asserta('$aleph_search'(nextnode,none)).
 4314
 4315set_up_builtins:-
 4316	gen_nlitnum(Cut),
 4317	asserta('$aleph_sat_litinfo'(Cut,0,'!',[],[],[])).
 4318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 4319% T H R E A D S
 4320
 4321% multi-threaded randomised local search
 4322rls_search(1, MaxTries, Time, Nodes, Selected) :-
 4323 	!,
 4324	retractall('$aleph_search'(rls_restart,_)),
 4325	retractall('$aleph_search'(rls_nodes,_)),
 4326	retractall('$aleph_search'(rls_selected,_)),
 4327	asserta('$aleph_search'(rls_restart,1)),
 4328	setting(evalfn,Evalfn),
 4329	get_start_label(Evalfn,Label),
 4330	set(best,Label),
 4331	get_search_settings(S),
 4332	arg(4,S,SearchStrat/_),
 4333	('$aleph_sat'(example,example(Num,Type)) ->
 4334		example(Num,Type,Example),
 4335		asserta('$aleph_search'(rls_selected,selected(Label,
 4336						(Example:-true),[Num-Num],[])));
 4337		asserta('$aleph_search'(rls_selected,selected(Label,
 4338						(false:-true),[],[])))
 4339	),
 4340 	asserta('$aleph_search'(rls_nodes,0)),
 4341 	stopwatch(Start),
 4342	estimate_numbers(_),	
 4343 	repeat,
 4344 	retract('$aleph_search'(rls_restart,R)),
 4345 	R1 is R + 1,
 4346 	asserta('$aleph_search'(rls_restart,R1)),
 4347 	rls_thread(R, SearchStrat, Label, Nodes0, selected(Best,RCl,PCov,NCov)),
 4348 	Best = [_,_,_,F|_],
 4349 	'$aleph_search'(rls_selected,selected([_,_,_,F1|_],_,_,_)),
 4350 	(F1 >= F -> true;
 4351 		retract('$aleph_search'(rls_selected,selected([_,_,_,F1|_],
 4352							_,_,_))),
 4353 		asserta('$aleph_search'(rls_selected,selected(Best,RCl,
 4354							PCov,NCov))),
 4355 		set(best,Best)
 4356 	),
 4357 	setting(best,BestSoFar),
 4358 	retract('$aleph_search'(rls_nodes,Nodes1)),
 4359 	Nodes2 is Nodes0 + Nodes1,
 4360 	asserta('$aleph_search'(rls_nodes,Nodes2)),
 4361 	(R1 > MaxTries; discontinue_search(S,BestSoFar/_,Nodes2)),
 4362 	!,
 4363 	stopwatch(Stop),
 4364 	Time is Stop - Start,
 4365 	retractall('$aleph_search'(rls_restart,_)),
 4366	retract('$aleph_search'(rls_nodes,Nodes)),
 4367        retract('$aleph_search'(rls_selected,Selected)).
 4368rls_search(N, MaxTries, Time, Nodes, Selected) :-
 4369	retractall('$aleph_search'(rls_restart,_)),
 4370	retractall('$aleph_search'(rls_nodes,_)),
 4371	retractall('$aleph_search'(rls_selected,_)),
 4372	setting(evalfn,Evalfn),
 4373	get_start_label(Evalfn,Label),
 4374	set(best,Label),
 4375	get_search_settings(S),
 4376	arg(4,S,SearchStrat/_),
 4377	('$aleph_sat'(example,example(Num,Type)) ->
 4378		example(Num,Type,Example),
 4379		asserta('$aleph_search'(rls_selected,selected(Label,
 4380						(Example:-true),[Num-Num],[])));
 4381		asserta('$aleph_search'(rls_selected,selected(Label,
 4382						(false:-true),[],[])))
 4383	),
 4384 	asserta('$aleph_search'(rls_nodes,0)),
 4385	estimate_numbers(_),	% so all threads can use same estimates
 4386	thread_self(Master),
 4387	message_queue_create(Queue),
 4388	create_worker_pool(N, Master, Queue, WorkerIds),
 4389	forall(between(1, MaxTries, R),
 4390	       thread_send_message(Queue, rls_restart(R, SearchStrat, Label))),
 4391	collect_results(rls_restart,MaxTries,[0,S],[Time|_]),
 4392	kill_worker_pool(Queue, WorkerIds),
 4393 	retractall('$aleph_search'(rls_restart,_)),
 4394	retract('$aleph_search'(rls_nodes,Nodes)),
 4395        retract('$aleph_search'(rls_selected,Selected)).
 4396
 4397rls_thread(R, SearchStrat, Label, Nodes0, selected(Best,RCl,PCov,NCov)) :-
 4398	retractall('$aleph_search'(best_refinement,_)),
 4399	retractall('$aleph_search'(last_refinement,_)),
 4400        retractall('$aleph_search'(rls_move,_)),
 4401        retractall('$aleph_search'(rls_parentstats,_)),
 4402	retractall('$aleph_search_seen'(_,_)),
 4403        asserta('$aleph_search'(rls_move,1)),
 4404        asserta('$aleph_search'(rls_parentstats,stats(Label,[],[]))),
 4405        p1_message('restart'), p_message(R),
 4406        find_clause(SearchStrat),
 4407	'$aleph_search'(current,current(_,Nodes0,_)),
 4408	'$aleph_search'(selected,selected(Best,RCl,PCov,NCov)),
 4409	retractall('$aleph_search'(best_refinement,_)),
 4410	retractall('$aleph_search'(last_refinement,_)),
 4411        retractall('$aleph_search'(rls_move,_)),
 4412        retractall('$aleph_search'(rls_parentstats,_)).
 4413
 4414
 4415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 4416% T H R E A D S
 4417
 4418create_worker_pool(N, Master, Queue, WorkerIds) :-
 4419	create_worker_pool(1, N, Master, Queue, WorkerIds).
 4420
 4421create_worker_pool(I, N, _, _, []) :-
 4422	I > N, !.
 4423create_worker_pool(I, N, Master, Queue, [Id|T]) :-
 4424	atom_concat(worker_, I, Alias),
 4425	thread_create(worker(Queue, Master), Id, [alias(Alias)]),
 4426	I2 is I + 1,
 4427	create_worker_pool(I2, N, Master, Queue, T).
 4428
 4429kill_worker_pool(Queue, WorkerIds) :-
 4430	p_message('Killing workers'),
 4431	forall(aleph_member(Worker, WorkerIds),
 4432	       kill_worker(Queue, Worker)),
 4433	p_message('Waiting for workers'),
 4434	forall(aleph_member(Worker, WorkerIds),
 4435	       thread_join(Worker, _)),
 4436	message_queue_destroy(Queue),
 4437	p_message('Ok, all done').
 4438
 4439kill_worker(Queue, Worker) :-
 4440	thread_send_message(Queue, all_done),
 4441	thread_signal(Worker, throw(surplus_to_requirements)).
 4442
 4443worker(Queue, Master) :-
 4444	thread_get_message(Queue, Message),
 4445	work(Message, Master),
 4446	worker(Queue, Master).
 4447
 4448work(rls_restart(R, SearchStrat, Label), Master) :-
 4449	statistics(cputime, CPU0),
 4450	rls_thread(R, SearchStrat, Label, Nodes, Selected),
 4451	statistics(cputime, CPU1),
 4452	CPU is CPU1 - CPU0,
 4453	thread_send_message(Master, done(CPU, Nodes, Selected)).
 4454work(all_done, _) :-
 4455	thread_exit(done).
 4456
 4457collect_results(rls_restart,NResults,In,Out):-
 4458        collect_results(0,NResults,rls_restart,In,Out).
 4459
 4460collect_results(R0,MaxR,Flag,In,Out):-
 4461        thread_get_message(Message),
 4462        collect(Flag,Message,In,Out1,Done),
 4463        R1 is R0 + 1,
 4464        (   (Done == false,
 4465            R1 < MaxR)
 4466        ->  collect_results(R1,MaxR,Flag,Out1,Out)
 4467        ;   Out = Out1
 4468        ).
 4469
 4470collect(rls_restart,done(CPU, Nodes, selected(Best,RCl,PCov,NCov)),[T0,S], [T1,S],Done) :-
 4471        T1 is CPU + T0,
 4472        Best = [_,_,_,F|_],
 4473        '$aleph_search'(rls_selected,selected([_,_,_,F1|_],_,_,_)),
 4474        (F1 >= F -> true;
 4475                retract('$aleph_search'(rls_selected,selected(
 4476                                                [_,_,_,F1|_],_,_,_))),
 4477                asserta('$aleph_search'(rls_selected,selected(Best,
 4478                                                RCl,PCov,NCov))),
 4479                set(best,Best)),
 4480        setting(best,BestSoFar),
 4481        retract('$aleph_search'(rls_nodes,Nodes1)),
 4482        Nodes2 is Nodes + Nodes1,
 4483        asserta('$aleph_search'(rls_nodes,Nodes2)),
 4484        (   discontinue_search(S,BestSoFar/_,Nodes2)
 4485        ->  Done = true
 4486        ;   Done = false
 4487        ).
 4488
 4489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 4490% C O N T R O L
 4491
 4492% induce_clauses/0: the basic theory construction predicate
 4493% constructs theories 1 clause at a time
 4494induce_clauses:-
 4495	setting(interactive,true), !,
 4496	induce_incremental.
 4497induce_clauses:-
 4498	induce.
 4499
 4500% induce/0: non-interactive theory construction
 4501% constructs theories 1 clause at a time
 4502% does greedy cover removal after each clause found
 4503induce:-
 4504	clean_up,
 4505	set(greedy,true),
 4506	retractall('$aleph_global'(search_stats,search_stats(_,_))),
 4507        '$aleph_global'(atoms_left,atoms_left(pos,PosSet)),
 4508        PosSet \= [],
 4509	store(portray_search),
 4510	set(portray_search,false),
 4511        setting(samplesize,S),
 4512	setting(abduce,Abduce),
 4513	record_settings,
 4514        stopwatch(StartClock),
 4515        repeat,
 4516        gen_sample(pos,S),
 4517	retractall('$aleph_global'(besthyp,besthyp(_,_,_,_,_))),
 4518        asserta('$aleph_global'(besthyp,besthyp([-inf,0,1,-inf],0,(false),[],[]))),
 4519        get_besthyp(Abduce),
 4520        (setting(gcws,true) -> sphyp, addgcws; addhyp),
 4521	show_atoms_left,
 4522	record_atoms_left,
 4523        '$aleph_global'(atoms_left,atoms_left(pos,[])),
 4524        stopwatch(StopClock),
 4525        Time is StopClock - StartClock,
 4526        show(theory),
 4527        record_theory(Time),
 4528	noset(greedy),
 4529	reinstate(portray_search),
 4530        p1_message('time taken'), p_message(Time), 
 4531	show_total_stats,
 4532	record_total_stats, !.
 4533induce.
 4534
 4535% construct theories 1 clause at a time
 4536% does not perform greedy cover removal after each clause found
 4537% constructs unique ``maximum cover set'' solution
 4538% 	by obtaining the best clause covering each example
 4539% slow
 4540induce_max:-
 4541	clean_up,
 4542	retractall('$aleph_global'(search_stats,search_stats(_,_))),
 4543	'$aleph_global'(atoms,atoms(pos,PosSet)),
 4544	PosSet \= [],
 4545	store(portray_search),
 4546	set(portray_search,false),
 4547	record_settings,
 4548	stopwatch(StartClock),
 4549	set(maxcover,true),
 4550	induce_max(PosSet),
 4551	stopwatch(StopClock),
 4552	Time is StopClock - StartClock,
 4553	show(theory),
 4554	record_theory(Time),
 4555	noset(maxcover),
 4556	reinstate(portray_search),
 4557	reinstate(greedy),
 4558	p1_message('time taken'), p_message(Time),
 4559	show_total_stats,
 4560	record_total_stats, !.
 4561induce_max.
 4562
 4563induce_max([]).
 4564induce_max([Start-Finish|Intervals]):-
 4565	asserta('$aleph_local'(counter,Start)),
 4566	induce_max1(Finish),
 4567	induce_max(Intervals).
 4568
 4569induce_max1(Finish):-
 4570        '$aleph_local'(counter,S),
 4571        S =< Finish, !,
 4572	(setting(resample,Resample) -> true; Resample = 1),
 4573        repeat,
 4574        retract('$aleph_local'(counter,Start)),
 4575	gen_sample(Resample,pos,Start),
 4576	get_besthyp(false),
 4577        update_coverset(pos,Start),
 4578        Next is Start+1,
 4579        assertz('$aleph_local'(counter,Next)),
 4580        Next > Finish, !,
 4581	retract('$aleph_local'(counter,Next)).
 4582induce_max1(_).
 4583
 4584% construct theories 1 clause at a time
 4585% does not perform greedy cover removal after each clause found
 4586induce_cover:-
 4587	clean_up,
 4588	retractall('$aleph_global'(search_stats,search_stats(_,_))),
 4589	'$aleph_global'(atoms,atoms(pos,PosSet)),
 4590	PosSet \= [],
 4591	store(portray_search),
 4592	set(portray_search,false),
 4593	setting(samplesize,S),
 4594	setting(abduce,Abduce),
 4595	record_settings,
 4596	stopwatch(StartClock),
 4597        repeat,
 4598	gen_sample(pos,S),
 4599	asserta('$aleph_global'(besthyp,besthyp([-inf,0,1,-inf],0,
 4600					(false),[],[]))),
 4601	get_besthyp(Abduce),
 4602	addhyp,
 4603        '$aleph_global'(atoms_left,atoms_left(pos,[])),
 4604	stopwatch(StopClock),
 4605	Time is StopClock - StartClock,
 4606        show(theory), 
 4607	record_theory(Time),
 4608	reinstate(portray_search),
 4609	reinstate(greedy),
 4610	p1_message('time taken'), p_message(Time), 
 4611	show_total_stats,
 4612	record_total_stats, !.
 4613induce_cover.
 4614
 4615% rudimentary version of an interactive, incremental rule learner
 4616% repeatedly does the following:
 4617%	1. ask the user for an example
 4618%		default is to use a new positive example from previous search
 4619%		if user responds with Ctrl-d (eof) then search stops
 4620%		if user responds with "ok" then default is used
 4621%		otherwise user has to provide an example
 4622%	2. construct bottom clause using that example
 4623%		expects to have appropriate mode declarations
 4624%	3. search for the best clause C
 4625%	4. ask the user about C who can respond with
 4626%		ok: clause added to theory
 4627%		prune: statement added to prevent future
 4628%				clauses that are subsumed by C
 4629%		overgeneral: constraint added to prevent future
 4630%				clauses that subsume C
 4631%		overgeneral because not(E): E is added as a negative example
 4632%		overspecific: C is added as new positive example
 4633%		overspecific because E: E is added as a new positive example
 4634%		X: where X is some aleph command like "covers"
 4635%		Ctrl-d (eof): return to Step 1		
 4636induce_incremental:-
 4637	clean_up,
 4638	retractall('$aleph_global'(search_stats,search_stats(_,_))),
 4639	store_values([interactive,portray_search,proof_strategy,mode]),
 4640	set(portray_search,false),
 4641	set(proof_strategy,sld),
 4642	set(interactive,true),
 4643	record_settings,
 4644        stopwatch(StartClock),
 4645        repeat,
 4646	ask_example(E),
 4647	((E = end_of_file; E = none) -> true;
 4648		once(record_example(check,pos,E,N)),
 4649		retractall('$aleph_global'(example_selected,
 4650						example_selected(_,_))),
 4651        	asserta('$aleph_global'(example_selected,
 4652						example_selected(pos,N))),
 4653		once(sat(N)),
 4654		once(reduce),
 4655		once(process_hypothesis),
 4656		fail),
 4657	!,
 4658        stopwatch(StopClock),
 4659        Time is StopClock - StartClock,
 4660        show(theory),
 4661	show(pos),
 4662	show(neg),
 4663	show(false/0),
 4664	show(prune/1),
 4665        record_theory(Time),
 4666	reinstate_values([interactive,portray_search,proof_strategy,mode]),
 4667        p1_message('time taken'), p_message(Time).
 4668
 4669% induce_theory/0: does theory-level search
 4670% currently only with search = rls; and evalfn = accuracy
 4671induce_theory:-
 4672	setting(search,Search),
 4673	induce_theory(Search).
 4674
 4675% induce entire theories from batch data
 4676% using a randomised local search
 4677% 	currently, this can use either: simulated annealing with a fixed temp,
 4678% 	GSAT, or a WSAT-like algorithm
 4679% 	the choice of these is specified by the parameter: rls_type
 4680% 	all methods employ random multiple restarts
 4681% 	and a limit on the number of moves
 4682%       	the number of restarts is specified by set(tries,...)
 4683%       	the number of moves is specified by set(moves,...)
 4684% 	annealing currently restricted to using a fixed temperature
 4685%       	the temperature is specified by set(temperature,...)
 4686%       	the fixed temp. makes it equivalent to the Metropolis alg.
 4687% 	WSAT requires a ``random-walk probability'' 
 4688%       	the walk probability is specified by set(walk,...)
 4689%       	a walk probability of 0 is equivalent to doing standard GSAT
 4690% 	theory accuracy is the evaluation function
 4691induce_theory(rls):-
 4692	clean_up,
 4693	retractall('$aleph_global'(search_stats,search_stats(_,_))),
 4694        store(evalfn),
 4695        set(evalfn,accuracy),
 4696	record_settings,
 4697	find_theory(rls),
 4698        reinstate(evalfn),
 4699	show_total_stats,
 4700	record_total_stats, !.
 4701induce_theory(_).
 4702
 4703
 4704% induce_constraints/0: search for logical constraints that
 4705% hold in the background knowledge
 4706% A constraint is a clause of the form false:-... 
 4707% This is modelled on the Claudien program developed by
 4708% L. De Raedt and his colleagues in Leuven
 4709% Constraints that are ``nearly true'' can be obtained
 4710% by altering the noise setting
 4711% All constraints found are stored as `good clauses'.
 4712induce_constraints:-
 4713	clean_up,
 4714	retractall('$aleph_global'(search_stats,search_stats(_,_))),
 4715	store_values([portray_search,search,construct_bottom,good,goodfile]),
 4716	noset(goodfile),
 4717	set(portray_search,false),
 4718	set(construct_bottom,false),
 4719	set(search,ic),
 4720	set(good,true),
 4721	sat(uspec,0),
 4722	reduce,
 4723	show(constraints),
 4724	reinstate_values([portray_search,search,construct_bottom,good,goodfile]),
 4725	show_total_stats,
 4726	record_total_stats, !.
 4727induce_constraints.
 4728
 4729% induce_modes/0: search for an acceptable set of mode declarations
 4730induce_modes:-
 4731	clean_up,
 4732	store_values([typeoverlap]),
 4733	search_modes,
 4734	reinstate_values([typeoverlap]),
 4735	show(modes).
 4736
 4737% induce_features/0: search for interesting boolean features
 4738% each good clause found in a search constitutes a new boolean feature
 4739% the maximum number of features is controlled by set(max_features,F)
 4740% the features are constructed by doing the following:
 4741% while (number of features =< F) do: 
 4742%       (a) randomly select an example;
 4743%       (b) search for good clauses using the example selected;
 4744%       (c) construct new features using good clauses
 4745
 4746induce_features:-
 4747	clean_up,
 4748	store_values([good,check_good,updateback,construct_features,samplesize,greedy,explore,lazy_on_contradiction]),
 4749	set(good,true),
 4750	set(check_good,true),
 4751	set(updateback,false),
 4752	set(construct_features,true),
 4753	set(lazy_on_contradiction,true),
 4754	(setting(feature_construction,exhaustive) -> set(explore,true);
 4755			true),
 4756	setting(max_features,FMax),
 4757        record_settings,
 4758        stopwatch(StartClock),
 4759        '$aleph_global'(atoms_left,atoms_left(pos,AtomsLeft)), 
 4760	repeat,
 4761        gen_sample(pos,0),
 4762	retractall('$aleph_global'(besthyp,besthyp(_,_,_,_,_))),
 4763        asserta('$aleph_global'(besthyp,besthyp([-inf,0,1,-inf],0,(false),[],[]))),
 4764        get_besthyp(false),
 4765        addhyp,
 4766	show_atoms_left,
 4767	record_atoms_left,
 4768        (('$aleph_search'(last_good,LastGood), LastGood >= FMax);
 4769        	'$aleph_global'(atoms_left,atoms_left(pos,[]))), !,
 4770	gen_features,
 4771        stopwatch(StopClock),
 4772        Time is StopClock - StartClock,
 4773	show(features),
 4774        record_features(Time),
 4775        retract('$aleph_global'(atoms_left,atoms_left(pos,_))), 
 4776        assertz('$aleph_global'(atoms_left,atoms_left(pos,AtomsLeft))), 
 4777        reinstate_values([good,check_good,updateback,construct_features,samplesize,greedy,explore,lazy_on_contradiction]), !.
 4778induce_features.
 4779
 4780% induce_tree/0: construct a theory using recursive partitioning
 4781% rules are obtained by building a tree 
 4782% the tree constructed can be one of 4 types
 4783%        classification, regression, class_probability or model
 4784%        the type is set by set(tree_type,...)
 4785% In addition, the following parameters are relevant
 4786%        set(classes,ListofClasses): when tree_type is classification or
 4787%                                    or class_probability
 4788%        set(prune_tree,Flag): for pruning rules from a tree
 4789%        set(confidence,C): for pruning of rules as described by
 4790%                           J R Quinlan in the C4.5 book
 4791%        set(lookahead,L): lookahead for the refinement operator to avoid
 4792%                          local zero-gain literals
 4793%        set(dependent,A): argument of the dependent variable in the examples
 4794% The basic procedure attempts to construct a tree to predict the dependent
 4795% variable in the examples. Note that the mode declarations must specify the
 4796% variable as an output argument. Paths from root to leaf constitute clauses.
 4797% Tree-construction is viewed as a refinement operation: any leaf can currently
 4798% be refined by extending the corresponding clause. The extension is done using
 4799% Aleph's automatic refinement operator that extends clauses within the mode
 4800% language. A lookahead option allows additions to include several literals.
 4801% Classification problems currently use entropy gain to measure worth of additions.
 4802% Regression and model trees use reduction in standard deviation to measure
 4803% worth of additions. This is not quite correct for the latter.
 4804% Pruning for classification is done on the final set of clauses from the tree.
 4805% The technique used here is the reduced-error pruning method.
 4806% For classification trees, this is identical to the one proposed by
 4807% Quinlan in C4.5: Programs for Machine Learning, Morgan Kauffmann.
 4808% For regression and model trees, this is done by using a pessimistic estimate
 4809% of the sample standard deviation. This assumes normality of observed values
 4810% in a leaf. This method and others have been studied by L. Torgo in
 4811% "A Comparative Study of Reliable Error Estimators for Pruning Regression
 4812% Trees"
 4813% Following work by F Provost and P Domingos, pruning is not employed
 4814% for class probability prediction.
 4815% Currently no pruning is performed for model trees.
 4816induce_tree:-
 4817	clean_up,
 4818	setting(tree_type,Type),
 4819	store_values([refine]),
 4820	set(refine,auto),
 4821	setting(mingain,MinGain),
 4822	(MinGain =< 0.0 ->
 4823		err_message('inappropriate setting for mingain'),
 4824		fail;
 4825		true
 4826	),
 4827	record_settings,
 4828	stopwatch(StartClock),
 4829	construct_tree(Type),
 4830	stopwatch(StopClock),
 4831	Time is StopClock - StartClock,
 4832	show(theory),
 4833	record_theory(Time),
 4834	reinstate_values([refine]), !.
 4835induce_tree.
 4836
 4837% utilities for the induce predicates
 4838
 4839
 4840% randomly pick a positive example and construct bottom clause
 4841%	example is from those uncovered by current theory
 4842%	and whose bottom clause has not been stored away previously
 4843% 	makes at most 100 attempts to find such an example
 4844rsat:-
 4845        '$aleph_global'(atoms_left,atoms_left(pos,PosSet)),
 4846        PosSet \= [],
 4847	store(resample),
 4848	set(resample,1),
 4849	rsat(100),
 4850	reinstate(resample).
 4851
 4852rsat(0):- !.
 4853rsat(N):-
 4854        gen_sample(pos,1),
 4855	'$aleph_global'(example_selected,example_selected(pos,Num)),
 4856	(\+('$aleph_sat'(stored,stored(Num,pos,_))) ->
 4857		!,
 4858		retract('$aleph_global'(example_selected,
 4859					example_selected(pos,Num))),
 4860		sat(pos,Num);
 4861		N1 is N - 1,
 4862		rsat(N1)).
 4863
 4864get_besthyp(AbduceFlag):-
 4865	retract('$aleph_global'(example_selected,
 4866				example_selected(pos,Num))),
 4867	reset_best_label,	 % set-up target to beat
 4868	sat(Num),
 4869	reduce,
 4870	update_besthyp(Num),
 4871	(AbduceFlag = true ->
 4872        	example(Num,pos,Atom),
 4873		abgen(Atom,AbGen),
 4874		once(retract('$aleph_global'(hypothesis,
 4875				hypothesis(Label,_,PCover,NCover)))),
 4876		assert('$aleph_global'(hypothesis,
 4877				hypothesis(Label,AbGen,PCover,NCover))),
 4878		update_besthyp(Num);
 4879		true),
 4880	fail.
 4881get_besthyp(_):-
 4882        retract('$aleph_global'(besthyp,besthyp(L,Num,H,PC,NC))),
 4883	H \= false, !,
 4884	((setting(samplesize,S),S>1)->
 4885		setting(nodes,Nodes),
 4886		show_clause(sample,L,H,Nodes),
 4887		record_clause(sample,L,H,Nodes);
 4888		true),
 4889        add_hyp(L,H,PC,NC),
 4890	asserta('$aleph_global'(example_selected,
 4891				example_selected(pos,Num))), !.
 4892get_besthyp(_).
 4893
 4894
 4895reset_best_label:-
 4896	'$aleph_global'(besthyp,besthyp(Label1,_,Clause,P,N)),
 4897	'$aleph_search'(best_label,Label/_),
 4898	Label = [_,_,L,GainE|_],
 4899	Label1 = [_,_,L1,Gain1E|_],
 4900        % Gain > Gain1, !,
 4901	arithmetic_expression_value(GainE,Gain),
 4902	arithmetic_expression_value(Gain1E,Gain1),
 4903        ((Gain1 > Gain);(Gain1 =:= Gain, L1 < L)), !,
 4904	retract('$aleph_search'(best_label,Label/_)),
 4905	asserta('$aleph_search'(best_label,Label1/0)),
 4906	retractall('$aleph_search'(selected,_)),
 4907	asserta('$aleph_search'(selected,selected(Label1,Clause,P,N))).
 4908reset_best_label.
 4909
 4910
 4911update_besthyp(Num):-
 4912	'$aleph_global'(hypothesis,hypothesis(Label,H,PCover,NCover)),
 4913	'$aleph_global'(besthyp,besthyp(Label1,_,_,_,_)),
 4914	Label = [_,_,L,GainE|_],
 4915	Label1 = [_,_,L1,Gain1E|_],
 4916        % Gain > Gain1, !,
 4917	arithmetic_expression_value(GainE,Gain),
 4918	arithmetic_expression_value(Gain1E,Gain1),
 4919        ((Gain > Gain1);(Gain =:= Gain1, L < L1)), !,
 4920	retract('$aleph_global'(besthyp,besthyp(Label1,_,_,_,_))),
 4921	assertz('$aleph_global'(besthyp,besthyp(Label,Num,H,PCover,NCover))).
 4922update_besthyp(_).
 4923
 4924
 4925% generate a new feature from a good clause
 4926gen_features:-
 4927	aleph_abolish('$aleph_feature'/2),
 4928	(setting(dependent,PredictArg) -> true; PredictArg is 0),
 4929        (setting(minscore,FMin) -> true; FMin = -inf),
 4930	'$aleph_good'(_,Label,Clause),
 4931	Label = [_,_,_,FE|_],
 4932	arithmetic_expression_value(FE,F),
 4933	F >= FMin,
 4934	split_clause(Clause,Head,Body),
 4935	Body \= true,
 4936	functor(Head,Name,Arity),
 4937	functor(Template,Name,Arity),
 4938	copy_iargs(Arity,Head,Template,PredictArg),
 4939	get_feature_class(PredictArg,Head,Body,Class),
 4940	gen_feature((Template:-Body),Label,Class),
 4941	fail.
 4942gen_features:-
 4943	(setting(dependent,PredictArg) -> true; PredictArg is 0),
 4944	setting(good,true),
 4945	setting(goodfile,File),
 4946	aleph_open(File,read,Stream),
 4947        (setting(minscore,FMin) -> true; FMin = -inf),
 4948	repeat,
 4949	read(Stream,Fact),
 4950	(Fact = '$aleph_good'(_,Label,Clause) ->
 4951		Label = [_,_,_,FE|_],
 4952		arithmetic_expression_value(FE,F),
 4953		F >= FMin,
 4954		split_clause(Clause,Head,Body),
 4955		Body \= true,
 4956		functor(Head,Name,Arity),
 4957		functor(Template,Name,Arity),
 4958		copy_iargs(Arity,Head,Template,PredictArg),
 4959		get_feature_class(PredictArg,Head,Body,Class),
 4960		gen_feature((Template:-Body),Label,Class),
 4961		fail;
 4962		close(Stream), !
 4963	).
 4964gen_features.
 4965
 4966get_feature_class(Argno,Head,Body,Class):-
 4967	has_class(Argno,Head,Body,Class), !.
 4968get_feature_class(_,_,_,_).
 4969
 4970has_class(Argno,Head,_,Class):-
 4971	arg(Argno,Head,Class),
 4972	ground(Class), !.
 4973has_class(Argno,Head,Body,Class):-
 4974	arg(Argno,Head,DepVar),
 4975	in((DepVar=Class),Body), 
 4976	ground(Class), !.
 4977
 4978ask_example(E):-
 4979	('$aleph_global'(example_selected,example_selected(pos,N)) ->
 4980		example(N,pos,E1);
 4981		E1 = none),
 4982	!,
 4983	show_options(example_selection),
 4984	tab(4),
 4985	write('Response '), p1_message(default:E1), write('?'), nl,
 4986	read(Response),
 4987	(Response = ok  -> E = E1; E = Response).
 4988
 4989process_hypothesis:-
 4990	show(hypothesis),
 4991	repeat,
 4992	show_options(hypothesis_selection),
 4993	tab(4),
 4994	write('Response?'), nl,
 4995	read(Response),
 4996	process_hypothesis(Response),
 4997	(Response = end_of_file; Response = none), !.
 4998
 4999
 5000process_hypothesis(end_of_file):-
 5001	nl, nl, !.
 5002process_hypothesis(none):-
 5003	nl, nl, !.
 5004process_hypothesis(ok):-
 5005	!,
 5006	update_theory(_),
 5007	nl, p_message('added new clause').
 5008process_hypothesis(prune):-
 5009        !,
 5010        retract('$aleph_global'(hypothesis,hypothesis(_,H,_,_))),
 5011        Prune = (
 5012                hypothesis(Head,Body,_),
 5013                goals_to_list(Body,BodyL),
 5014                clause_to_list(H,HL),
 5015                aleph_subsumes(HL,[Head|BodyL])),
 5016        assertz((prune(H):- Prune)),
 5017        nl, p_message('added new prune statement').
 5018process_hypothesis(overgeneral):-
 5019        !,
 5020        retract('$aleph_global'(hypothesis,hypothesis(_,H,_,_))),
 5021        Constraint = (
 5022                hypothesis(Head,Body,_),
 5023                goals_to_list(Body,BodyL),
 5024                clause_to_list(H,HL),
 5025                aleph_subsumes([Head|BodyL],HL)),
 5026        assertz((false:- Constraint)),
 5027        nl, p_message('added new constraint'). 
 5028process_hypothesis(overgeneral because not(E)):-
 5029	!,
 5030	record_example(check,neg,E,_),
 5031	nl, p_message('added new negative example').
 5032process_hypothesis(overspecific):-
 5033	!,
 5034        retract('$aleph_global'(hypothesis,hypothesis(_,H,_,_))),
 5035	(retract('$aleph_global'(example_selected,example_selected(_,_)))->
 5036		true;
 5037		true),
 5038	record_example(check,pos,H,N),
 5039	asserta('$aleph_global'(example_selected,example_selected(pos,N))),
 5040	nl, p_message('added new positive example').
 5041process_hypothesis(overspecific because E):-
 5042	!,
 5043        retract('$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
 5044	(retract('$aleph_global'(example_selected,example_selected(_,_)))->
 5045		true;
 5046		true),
 5047	record_example(check,pos,E,N),
 5048	asserta('$aleph_global'(example_selected,example_selected(pos,N))),
 5049	nl, p_message('added new positive example').
 5050process_hypothesis(AlephCommand):-
 5051	AlephCommand.
 5052
 5053show_options(example_selection):-
 5054	nl,
 5055	tab(4),
 5056	write('Options:'), nl,
 5057	tab(8),
 5058	write('-> "ok." to accept default example'), nl,
 5059	tab(8),
 5060	write('-> Enter an example'), nl, 
 5061	tab(8),
 5062	write('-> ctrl-D or "none." to end'), nl, nl.
 5063show_options(hypothesis_selection):-
 5064	nl,
 5065	tab(4),
 5066	write('Options:'), nl,
 5067	tab(8),
 5068	write('-> "ok." to accept clause'), nl,
 5069	tab(8),
 5070        write('-> "prune." to prune clause and its refinements from the search'), nl,
 5071        tab(8),
 5072	write('-> "overgeneral." to add clause as a constraint'), nl, 
 5073	tab(8),
 5074	write('-> "overgeneral because not(E)." to add E as a negative example'), nl, 
 5075	tab(8),
 5076	write('-> "overspecific." to add clause as a positive example'), nl, 
 5077	tab(8),
 5078	write('-> "overspecific because E." to add E as a positive example'), nl, 
 5079	tab(8),
 5080	write('-> any Aleph command'), nl, 
 5081	tab(8),
 5082	write('-> ctrl-D or "none." to end'), nl, nl.
 5083	
 5084
 5085get_performance:-
 5086	setting(evalfn,Evalfn),
 5087	(Evalfn = sd; Evalfn = mse), !.
 5088get_performance:-
 5089	(setting(train_pos,PFile) ->
 5090		test(PFile,noshow,Tp,TotPos),
 5091		Fn is TotPos - Tp;
 5092		TotPos = 0, Tp = 0, Fn = 0),
 5093	(setting(train_neg,NFile) ->
 5094		test(NFile,noshow,Fp,TotNeg),
 5095		Tn is TotNeg - Fp;
 5096		TotNeg = 0, Tn = 0, Fp = 0),
 5097	TotPos + TotNeg > 0,
 5098	p_message('Training set performance'),
 5099	write_cmatrix([Tp,Fp,Fn,Tn]),
 5100	p1_message('Training set summary'), p_message([Tp,Fp,Fn,Tn]),
 5101	fail.
 5102get_performance:-
 5103	(setting(test_pos,PFile) ->
 5104		test(PFile,noshow,Tp,TotPos),
 5105		Fn is TotPos - Tp;
 5106		TotPos = 0, Tp = 0, Fn = 0),
 5107	(setting(test_neg,NFile) ->
 5108		test(NFile,noshow,Fp,TotNeg),
 5109		Tn is TotNeg - Fp;
 5110		TotNeg = 0, Tn = 0, Fp = 0),
 5111	TotPos + TotNeg > 0,
 5112	p_message('Test set performance'),
 5113	write_cmatrix([Tp,Fp,Fn,Tn]),
 5114	p1_message('Test set summary'), p_message([Tp,Fp,Fn,Tn]),
 5115	fail.
 5116get_performance.
 5117
 5118write_cmatrix([Tp,Fp,Fn,Tn]):-
 5119        P is Tp + Fn, N is Fp + Tn,
 5120        PP is Tp + Fp, PN is Fn + Tn,
 5121        Total is PP + PN,
 5122        (Total = 0 -> Accuracy is 0.5; Accuracy is (Tp + Tn)/Total),
 5123        find_max_width([Tp,Fp,Fn,Tn,P,N,PP,PN,Total],0,W1),
 5124        W is W1 + 2,
 5125        tab(5), write(' '), tab(W), write('Actual'), nl,
 5126        tab(5), write(' '), write_entry(W,'+'), tab(6), write_entry(W,'-'), nl,
 5127        tab(5), write('+'),
 5128        write_entry(W,Tp), tab(6), write_entry(W,Fp), tab(6), write_entry(W,PP), nl,
 5129        write('Pred '), nl,
 5130        tab(5), write('-'),
 5131        write_entry(W,Fn), tab(6), write_entry(W,Tn), tab(6), write_entry(W,PN), nl, nl,
 5132        tab(5), write(' '), write_entry(W,P), tab(6), write_entry(W,N),
 5133        tab(6), write_entry(W,Total), nl, nl,
 5134        write('Accuracy = '), write(Accuracy), nl.
 5135
 5136 
 5137find_max_width([],W,W).
 5138find_max_width([V|T],W1,W):-
 5139        name(V,VList),
 5140        length(VList,VL),
 5141        (VL > W1 -> find_max_width(T,VL,W);
 5142                find_max_width(T,W1,W)).
 5143 
 5144write_entry(W,V):-
 5145        name(V,VList),
 5146        length(VList,VL),
 5147        Y is integer((W-VL)/2),
 5148        tab(Y), write(V), tab(Y).
 5149
 5150%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 5151% A B D U C T I O N
 5152
 5153% Generalisation of an abductive explanation for a fact.
 5154% The basic procedure is a simplified variant of S. Moyle's Alecto
 5155% program. Alecto is described in some detail in S. Moyle,
 5156% "Using Theory Completion to Learn a Navigation Control Program",
 5157% Proceedings of the Twelfth International Conference on ILP (ILP2002),
 5158% S. Matwin and C.A. Sammut (Eds), LNAI 2583, pp 182-197,
 5159% 2003.  
 5160% Alecto does the following: for each positive example,  an
 5161% abductive explanation is obtained. This explanation is set of
 5162% ground atoms. The union of abductive explanations from all
 5163% positive examples is formed (this is also a set of ground atoms).
 5164% These are then generalised to give the final theory. The
 5165% ground atoms in an abductive explanation are obtained using
 5166% Yamamoto's SOLD resolution or SOLDR (Skip Ordered Linear resolution for
 5167% Definite clauses). 
 5168% One complication with abductive learning is this: for a given
 5169% positive example to be provable, we require all the ground atoms
 5170% in its abductive explanation to be true. Correctly therefore,
 5171% we would need to assert the abductive explanation before
 5172% checking the utility of any hypothesis. To avoid unnecessary
 5173% asserts and retracts, the "pclause" trick is used here (see
 5174% record_testclause/0).
 5175
 5176abgen(Fact):-
 5177	abgen(Fact,_).
 5178	
 5179abgen(Fact,AbGen):-
 5180	retractall('$aleph_search'(abgenhyp,hypothesis(_,_,_,_))),
 5181	Minf is -inf,
 5182	asserta('$aleph_search'(abgenhyp,
 5183				hypothesis([Minf,0,1,Minf],[false],[],[]))),
 5184	setting(max_abducibles,Max),
 5185	abgen(Fact,Max,AbGen),
 5186	'$aleph_global'(hypothesis,hypothesis(Label,_,PCover,NCover)),
 5187	Label = [_,_,LE,GainE|_],
 5188	arithmetic_expression_value(LE,L),
 5189	arithmetic_expression_value(GainE,Gain),
 5190	'$aleph_search'(abgenhyp,hypothesis(Label1,_,_,_)),
 5191	Label1 = [_,_,L1E,Gain1E|_],
 5192	arithmetic_expression_value(L1E,L1),
 5193	arithmetic_expression_value(Gain1E,Gain1),
 5194	once(((Gain > Gain1); (Gain =:= Gain1, L < L1))),
 5195	once(retract('$aleph_search'(abgenhyp,hypothesis(_,_,_,_)))),
 5196	asserta('$aleph_search'(abgenhyp,
 5197			hypothesis(Label,AbGen,PCover,NCover))),
 5198	fail.
 5199abgen(_,AbGen):-
 5200	retractall('$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
 5201	'$aleph_search'(abgenhyp,hypothesis(Label,AbGen,PCover,NCover)),
 5202	asserta('$aleph_global'(hypothesis,
 5203			hypothesis(Label,AbGen,PCover,NCover))).
 5204
 5205abgen(Fact,Max,AbGen):-
 5206	sold_prove(Fact,AbAtoms),
 5207	ground(AbAtoms),
 5208	length(AbAtoms,N),
 5209	N =< Max,
 5210	prolog_type(Prolog),
 5211	(Prolog = yap ->
 5212		store_abduced_atoms(AbAtoms,AssertRefs);
 5213		store_abduced_atoms(AbAtoms)),
 5214	store(proof_strategy),
 5215	set(proof_strategy,sld),
 5216	gen_abduced_atoms(AbAtoms,AbGen),
 5217	reinstate(proof_strategy),
 5218	(Prolog = yap ->
 5219		erase_refs(AssertRefs);
 5220		remove_abduced_atoms(AbAtoms)).
 5221
 5222gen_abduced_atoms([],[]).
 5223gen_abduced_atoms([AbAtom|AbAtoms],[AbGen|AbGens]):-
 5224	functor(AbAtom,Name,Arity),
 5225	add_determinations(Name/Arity,true),
 5226	sat(AbAtom),
 5227	reduce,
 5228	'$aleph_global'(hypothesis,hypothesis(_,AbGen,_,_)),
 5229	remove_explained(AbAtoms,AbGen,AbAtoms1),
 5230	gen_abduced_atoms(AbAtoms1,AbGens).
 5231
 5232remove_explained([],_,[]).
 5233remove_explained([AbAtom|AbAtoms],(Head:-Body),Rest):-
 5234	\+((\+ ((AbAtom = Head), Body))), !,
 5235	remove_explained(AbAtoms,(Head:-Body),Rest).
 5236remove_explained([AbAtom|AbAtoms],(Head:-Body),[AbAtom|Rest]):-
 5237	remove_explained(AbAtoms,(Head:-Body),Rest).
 5238	
 5239store_abduced_atoms([],[]).
 5240store_abduced_atoms([AbAtom|AbAtoms],[DbRef|DbRefs]):-
 5241	assertz('$aleph_search'(abduced,pclause(AbAtom,true)),DbRef),
 5242	store_abduced_atoms(AbAtoms,DbRefs).
 5243
 5244store_abduced_atoms([]).
 5245store_abduced_atoms([AbAtom|AbAtoms]):-
 5246	assertz('$aleph_search'(abduced,pclause(AbAtom,true))),
 5247	store_abduced_atoms(AbAtoms).
 5248
 5249remove_abduced_atoms([]).
 5250remove_abduced_atoms([AbAtom|AbAtoms]):-
 5251	retract('$aleph_search'(abduced,pclause(AbAtom,true))),
 5252	remove_abduced_atoms(AbAtoms).
 5253
 5254
 5255%    sold_prove(+G,-A)
 5256% Where G is an input goal (comma separated conjunction of atoms)
 5257% and A is a list of atoms (containing the abductive explanation).
 5258% This procedure is due to S.Moyle
 5259sold_prove(Goal,SkippedGoals):-
 5260	soldnf_solve(Goal,Skipped),
 5261	sort(Skipped,SkippedGoals).
 5262
 5263soldnf_solve(Goal,Skipped):-
 5264	soldnf_solve(Goal,true,[],Skipped).    
 5265
 5266soldnf_solve((Goal,Goals),Status,SkippedSoFar,Skipped):-
 5267	!,
 5268	soldnf_solve(Goal,Status1,SkippedSoFar,Skipped1),
 5269	soldnf_solve(Goals,Status2,Skipped1,Skipped),
 5270	conj_status(Status1,Status2,Status).
 5271soldnf_solve(not(Goal),true,SkippedSoFar,Skipped):-
 5272	soldnf_solve(Goal,false,SkippedSoFar,Skipped).
 5273soldnf_solve(not(Goal),false,SkippedSoFar,Skipped):-
 5274	!,
 5275	soldnf_solve(Goal,true,SkippedSoFar,Skipped).
 5276soldnf_solve(Goal,Status,SkippedSoFar,SkippedSoFar):-
 5277	soldnf_builtin(Goal), !,
 5278	soldnfcall(Goal,Status).
 5279soldnf_solve(Goal,Status,SkippedSoFar,Skipped):-
 5280	soldnf_clause(Goal,Body),
 5281	soldnf_solve(Body,Status,SkippedSoFar,Skipped).
 5282soldnf_solve(Goal,true,SkippedSoFar,[Goal|SkippedSoFar]):-
 5283	skippable(Goal).
 5284
 5285soldnf_clause(Goal,_Body):-soldnf_builtin(Goal),!,fail.
 5286soldnf_clause(Goal,Body):-
 5287	clause(Goal,Body).
 5288
 5289soldnf_builtin(not(_Goal)):-!,fail.
 5290soldnf_builtin(A):-predicate_property(A,built_in).
 5291
 5292soldnfcall(Goal,true):-
 5293	Goal, !.
 5294soldnfcall(_,false).
 5295
 5296conj_status(true,true,true):- !.
 5297conj_status(_,_,false).
 5298
 5299skippable(Pred):-
 5300	functor(Pred,Name,Arity),
 5301	'$aleph_global'(abducible,abducible(Name/Arity)).
 5302
 5303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 5304% L A Z Y  E V A L U A T I O N
 5305
 5306
 5307% lazy_evaluate_theory(+Clauses,+Lazy,+Pos,+Neg,-Theory)
 5308%       evaluate lazy preds in a set of clauses
 5309%	untested
 5310lazy_evaluate_theory([],_,_,_,[]).
 5311lazy_evaluate_theory([Refine|T],LazyPreds,Pos,Neg,[Refine1|T1]):-
 5312	Refine = A-[B,C,D,Clause],
 5313        lazy_evaluate_refinement(D,Clause,LazyPreds,Pos,Neg,D1,Clause1),
 5314	Refine1 = A-[B,C,D1,Clause1],
 5315        lazy_evaluate_theory(T,LazyPreds,Pos,Neg,T1).
 5316
 5317% lazy evaluation of literals in a refinement operation
 5318lazy_evaluate_refinement([],Refine,Lazy,Pos,Neg,[],NewRefine):-
 5319	clause_to_list(Refine,Lits),
 5320	lazy_evaluate_refinement(Lits,Lazy,[],Pos,Neg,Lits1),
 5321	list_to_clause(Lits1,NewRefine), !.
 5322lazy_evaluate_refinement(Lits,_,Lazy,Pos,Neg,Lits1,NewRefine):-
 5323	Lits \= [],
 5324	lazy_evaluate_refinement(Lits,Lazy,[],Pos,Neg,Lits1),
 5325	get_pclause(Lits1,[],NewRefine,_,_,_), !.
 5326lazy_evaluate_refinement(Lits,Refine,_,_,_,Lits,Refine).
 5327
 5328
 5329lazy_evaluate_refinement([],_,L,_,_,L):- !.
 5330lazy_evaluate_refinement([Lit|Lits],LazyPreds,Path,PosCover,NegCover,Refine):-
 5331	lazy_evaluate([Lit],LazyPreds,Path,PosCover,NegCover,[Lit1]), 
 5332	aleph_append([Lit1],Path,Path1), !,
 5333	lazy_evaluate_refinement(Lits,LazyPreds,Path1,PosCover,NegCover,Refine).
 5334
 5335
 5336% lazy evaluation of specified literals
 5337% all #'d arguments of these literals are evaluated at reduction-time
 5338% From Version 5 (dated Sat Nov 29 13:02:36 GMT 2003), collects both
 5339% input and output args (previously only collected input args)
 5340lazy_evaluate(Lits,[],_,_,_,Lits):- !.
 5341lazy_evaluate([],_,_,_,_,[]):- !.
 5342lazy_evaluate([LitNum|LitNums],LazyPreds,Path,PosCover,NegCover,Lits):-
 5343	(integer(LitNum) ->
 5344		BottomExists = true,
 5345		'$aleph_sat_litinfo'(LitNum,Depth,Atom,I,O,D),
 5346		functor(Atom,Name,Arity),
 5347		aleph_member1(Name/Arity,LazyPreds), !,
 5348		get_pclause([LitNum|Path],[],(Lit:-(Goals)),_,_,_);
 5349		BottomExists = false,
 5350		Atom = LitNum,
 5351		Depth = 0,
 5352		functor(Atom,Name,Arity),
 5353		aleph_member1(Name/Arity,LazyPreds), !,
 5354		split_args(LitNum,_,I,O,C),
 5355		D = [],
 5356		list_to_clause([LitNum|Path],(Lit:-(Goals)))),
 5357	goals_to_clause(Goals,Clause),
 5358	lazy_prove(pos,Lit,Clause,PosCover),
 5359	('$aleph_global'(positive_only,positive_only(Name/Arity))->
 5360		true;
 5361		lazy_prove_negs(Lit,Clause,NegCover)),
 5362	functor(LazyLiteral,Name,Arity),
 5363	collect_args(I,LazyLiteral),
 5364	collect_args(O,LazyLiteral),
 5365	lazy_evaluate1(BottomExists,Atom,Depth,I,O,C,D,LazyLiteral,NewLits),
 5366	retractall('$aleph_local'(lazy_evaluate,_)),
 5367	lazy_evaluate(LitNums,LazyPreds,Path,PosCover,NegCover,NewLits1),
 5368	update_list(NewLits1,NewLits,Lits).
 5369lazy_evaluate([LitNum|LitNums],LazyPreds,Path,PosCover,NegCover,[LitNum|Lits]):-
 5370	lazy_evaluate(LitNums,LazyPreds,Path,PosCover,NegCover,Lits).
 5371
 5372lazy_prove_negs(Lit,Clause,_):-
 5373	'$aleph_global'(lazy_negs,set(lazy_negs,true)), !,
 5374	'$aleph_global'(atoms,atoms(neg,NegCover)),
 5375	lazy_prove(neg,Lit,Clause,NegCover).
 5376lazy_prove_negs(Lit,Clause,NegCover):-
 5377	lazy_prove(neg,Lit,Clause,NegCover).
 5378
 5379collect_args([],_).
 5380collect_args([Argno/_|Args],Literal):-
 5381	findall(Term,
 5382			('$aleph_local'(lazy_evaluate,eval(pos,Lit)),
 5383			tparg(Argno,Lit,Term)),
 5384		PTerms),
 5385	findall(Term,
 5386			('$aleph_local'(lazy_evaluate,eval(neg,Lit)),
 5387			tparg(Argno,Lit,Term)),
 5388		NTerms),
 5389	tparg(Argno,Literal,[PTerms,NTerms]),
 5390	collect_args(Args,Literal).
 5391
 5392% when construct_bottom = false
 5393% currently do not check if user's definition of lazily evaluated
 5394% literal corresponds to recall number in the modes
 5395lazy_evaluate1(false,Atom,_,I,O,C,_,Lit,NewLits):-
 5396	functor(Atom,Name,Arity),
 5397	p1_message('lazy evaluation'), p_message(Name),
 5398	functor(NewLit,Name,Arity),
 5399	findall(NewLit,(Lit,copy_args(Lit,NewLit,C)),NewLits),
 5400	copy_io_args(NewLits,Atom,I,O).
 5401
 5402lazy_evaluate1(true,Atom,Depth,I,O,_,D,Lit,NewLits):-
 5403	% '$aleph_sat'(lastlit,_),
 5404	call_library_pred(Atom,Depth,Lit,I,O,D),
 5405	findall(LitNum,(retract('$aleph_local'(lazy_evaluated,LitNum))),NewLits).
 5406
 5407call_library_pred(OldLit,Depth,Lit,I,O,D):-
 5408	functor(OldLit,Name,Arity),
 5409	'$aleph_global'(lazy_recall,lazy_recall(Name/Arity,Recall)),
 5410	asserta('$aleph_local'(callno,1)),
 5411	p1_message('lazy evaluation'), p_message(Name),
 5412	repeat,
 5413	evaluate(OldLit,Depth,Lit,I,O,D),
 5414	retract('$aleph_local'(callno,CallNo)),
 5415	NextCall is CallNo + 1,
 5416	asserta('$aleph_local'(callno,NextCall)),
 5417	NextCall > Recall,
 5418	!,
 5419	p_message('completed'),
 5420	retract('$aleph_local'(callno,NextCall)).
 5421	 
 5422evaluate(OldLit,_,Lit,I,O,D):-
 5423	functor(OldLit,Name,Arity),
 5424	functor(NewLit,Name,Arity),
 5425	Lit,
 5426	copy_args(OldLit,NewLit,I),
 5427	copy_args(OldLit,NewLit,O),
 5428	copy_consts(Lit,NewLit,Arity),
 5429	update_lit(LitNum,false,NewLit,I,O,D),
 5430	\+('$aleph_local'(lazy_evaluated,LitNum)),
 5431	asserta('$aleph_local'(lazy_evaluated,LitNum)), !.
 5432evaluate(_,_,_,_,_,_).
 5433
 5434copy_io_args([],_,_,_).
 5435copy_io_args([New|NewL],Old,I,O):-
 5436	copy_args(Old,New,I),
 5437	copy_args(Old,New,O),
 5438	copy_io_args(NewL,Old,I,O).
 5439
 5440copy_args(_,_,[]).
 5441copy_args(Old,New,[Arg/_|T]):-
 5442	tparg(Arg,Old,Term),
 5443	tparg(Arg,New,Term),
 5444	copy_args(Old,New,T), !.
 5445
 5446copy_consts(_,_,0):- !.
 5447copy_consts(Old,New,Arg):-
 5448	arg(Arg,Old,Term),
 5449	arg(Arg,New,Term1),
 5450	var(Term1), !,
 5451	Term1 = aleph_const(Term),
 5452	Arg0 is Arg - 1,
 5453	copy_consts(Old,New,Arg0).
 5454copy_consts(Old,New,Arg):-
 5455	Arg0 is Arg - 1,
 5456	copy_consts(Old,New,Arg0).
 5457
 5458% copy_modeterm(+Old,-New)
 5459%	copy term structure from Old to New
 5460%	by finding an appropriate mode declaration
 5461copy_modeterm(Lit1,Lit2):-
 5462	functor(Lit1,Name,Arity),
 5463	find_mode(mode,Name/Arity,Mode),
 5464	functor(Lit2,Name,Arity),
 5465	copy_modeterms(Mode,Lit2,Arity),
 5466	\+((\+ (Lit1 = Lit2))).
 5467
 5468% find_mode(+modetype,+Name/+Arity,-Mode)
 5469% find a mode for Name/Arity of type modetype
 5470find_mode(mode,Name/Arity,Mode):-
 5471	!,
 5472	functor(Mode,Name,Arity),
 5473	'$aleph_global'(mode,mode(_,Mode)).
 5474find_mode(modeh,Name/Arity,Mode):-
 5475	!,
 5476	functor(Mode,Name,Arity),
 5477	'$aleph_global'(modeh,modeh(_,Mode)).
 5478find_mode(modeb,Name/Arity,Mode):-
 5479	!,
 5480	functor(Mode,Name,Arity),
 5481	'$aleph_global'(modeb,modeb(_,Mode)).
 5482
 5483% copy_modeterms(+Mode,+Lit,+Arity)
 5484% 	copy all term structures in a mode template
 5485copy_modeterms(_,_,0):- !.
 5486copy_modeterms(Mode,Lit,Arg):-
 5487        arg(Arg,Mode,Term),
 5488	nonvar(Term),
 5489        functor(Term,Name,Arity),
 5490        \+((Name = '+'; Name = '-'; Name = '#')), !,
 5491        functor(NewTerm,Name,Arity),
 5492        arg(Arg,Lit,NewTerm),
 5493        copy_modeterms(Term,NewTerm,Arity),
 5494        Arg0 is Arg - 1,
 5495        copy_modeterms(Mode,Lit,Arg0).
 5496copy_modeterms(Mode,Lit,Arg):-
 5497        Arg0 is Arg - 1,
 5498        copy_modeterms(Mode,Lit,Arg0).
 5499
 5500
 5501% theorem-prover for lazy evaluation of literals
 5502lazy_prove(Type,Lit,Clause,Intervals):-
 5503        (Clause = (Head:-Body)->
 5504		lazy_prove(Intervals,Type,Lit,Head,Body);
 5505		lazy_prove(Intervals,Type,Lit,Clause,true)).
 5506
 5507lazy_prove([],_,_,_,_).
 5508lazy_prove([Interval|Intervals],Type,Lit,Head,Body):-
 5509        lazy_index_prove(Interval,Type,Lit,Head,Body),
 5510        lazy_prove(Intervals,Type,Lit,Head,Body).
 5511
 5512lazy_index_prove(Start-Finish,_,_,_,_):-
 5513        Start > Finish, !.
 5514lazy_index_prove(Start-Finish,Type,Lit,Head,Body):-
 5515        lazy_index_prove1(Type,Lit,Head,Body,Start),
 5516        Start1 is Start + 1,
 5517        lazy_index_prove(Start1-Finish,Type,Lit,Head,Body).
 5518
 5519% bind input args of lazy literal
 5520% each example gives an set of input bindings
 5521% this is different from Aleph 2 where only a single binding was obtained
 5522lazy_index_prove1(Type,Lit,Head,Body,Num):-
 5523        depth_bound_call((example(Num,Type,Head),Body)),
 5524	\+('$aleph_local'(lazy_evaluate,eval(Type,Lit))),
 5525        asserta('$aleph_local'(lazy_evaluate,eval(Type,Lit))),
 5526        fail.
 5527lazy_index_prove1(_,_,_,_,_).
 5528
 5529
 5530%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 5531% S L P
 5532% implemented as described by Muggleton, ILP-96
 5533
 5534condition_target:-
 5535	'$aleph_global'(condition,set(condition,true)),
 5536	add_generator,
 5537	'$aleph_global'(modeh,modeh(_,Pred)),
 5538	functor(Pred,Name,Arity),
 5539	p_message('conditioning'),
 5540	make_sname(Name,SName),
 5541	functor(SPred,SName,Arity),
 5542	SPred =.. [_|Args],
 5543	functor(Fact,Name,Arity),
 5544	example(_,_,Fact),
 5545	Fact =.. [_|Args], 
 5546	condition(SPred),
 5547	fail.
 5548condition_target:-
 5549	\+('$aleph_global'(condition,set(condition,true))),
 5550	add_generator, !.
 5551condition_target.
 5552
 5553
 5554add_generator:-
 5555	'$aleph_global'(modeh,modeh(_,Pred)),
 5556	functor(Pred,Name,Arity),
 5557	make_sname(Name,SName),
 5558	functor(SPred,SName,Arity),
 5559	(clause(SPred,_)-> 
 5560		true;
 5561		add_generator(Name/Arity),
 5562		p1_message('included generator'), p_message(SName/Arity)),
 5563	fail.
 5564add_generator.
 5565
 5566add_generator(Name/Arity):-
 5567	make_sname(Name,SName),
 5568	functor(SPred,SName,Arity),
 5569	find_mode(modeh,Name/Arity,Mode),
 5570	once(copy_modeterms(Mode,SPred,Arity)),
 5571	split_args(Mode,Mode,Input,Output,Constants),
 5572	range_restrict(Input,SPred,[],B1),
 5573	range_restrict(Output,SPred,B1,B2),
 5574	range_restrict(Constants,SPred,B2,B3),
 5575	list_to_goals(B3,Body),
 5576	\+(clause(SPred,Body)),
 5577	asserta((SPred:-Body)),
 5578	fail.
 5579add_generator(_).
 5580
 5581make_sname(Name,SName):-
 5582	concat(['*',Name],SName).
 5583
 5584range_restrict([],_,R,R).
 5585range_restrict([Pos/Type|T],Pred,R0,R):-
 5586	functor(TCheck,Type,1),
 5587	tparg(Pos,Pred,X),
 5588	arg(1,TCheck,X),
 5589	range_restrict(T,Pred,[TCheck|R0],R).
 5590
 5591
 5592condition(Fact):-
 5593	slprove(condition,Fact), !.
 5594condition(_).
 5595
 5596sample(_,0,[]):- !.
 5597sample(Name/Arity,N,S):-
 5598	functor(Pred,Name,Arity),
 5599	retractall('$aleph_local'(slp_samplenum,_)),
 5600	retractall('$aleph_local'(slp_sample,_)),
 5601	asserta('$aleph_local'(slp_samplenum,1)),
 5602	repeat,
 5603	slprove(stochastic,Pred),
 5604	asserta('$aleph_local'(slp_sample,Pred)),
 5605	retract('$aleph_local'(slp_samplenum,N1)),
 5606	N2 is N1 + 1,
 5607	asserta('$aleph_local'(slp_samplenum,N2)),
 5608	N2 > N,
 5609	!,
 5610	retract('$aleph_local'(slp_samplenum,N2)),
 5611	functor(Fact,Name,Arity),
 5612	findall(Fact,(retract('$aleph_local'(slp_sample,Fact))),S).
 5613
 5614gsample(Name/Arity,_):-
 5615        make_sname(Name,SName),
 5616        functor(SPred,SName,Arity),
 5617        clause(SPred,Body),
 5618        ground((SPred:-Body)), !,
 5619        update_gsample(Name/Arity,_).
 5620gsample(_,0):- !.
 5621gsample(Name/Arity,N):-
 5622	functor(Pred,Name,Arity),
 5623	make_sname(Name,SName),
 5624	functor(SPred,SName,Arity),
 5625	Pred =.. [_|Args],
 5626	retractall('$aleph_local'(slp_samplenum,_)),
 5627	asserta('$aleph_local'(slp_samplenum,0)),
 5628	repeat,
 5629	slprove(stochastic,SPred),
 5630	SPred =..[_|Args],
 5631	retract('$aleph_local'(slp_samplenum,N1)),
 5632	N2 is N1 + 1,
 5633	asserta('$aleph_local'(slp_samplenum,N2)),
 5634	assertz(example(N2,rand,Pred)),
 5635	N2 >= N,
 5636	!,
 5637	retract('$aleph_local'(slp_samplenum,N2)),
 5638	asserta('$aleph_global'(size,size(rand,N))),
 5639	asserta('$aleph_global'(last_example,last_example(rand,N))),
 5640	asserta('$aleph_global'(atoms,atoms(rand,[1-N]))),
 5641	asserta('$aleph_global'(atoms_left,atoms_left(rand,[1-N]))).
 5642
 5643update_gsample(Name/Arity,_):-
 5644        functor(Pred,Name,Arity),
 5645        make_sname(Name,SName),
 5646        functor(SPred,SName,Arity),
 5647        retractall('$aleph_global'(gsample,gsample(_))),
 5648	retractall('$aleph_local'(slp_samplenum,_)),
 5649        asserta('$aleph_local'(slp_samplenum,0)),
 5650        SPred =.. [_|Args],
 5651        Pred =.. [_|Args],
 5652        clause(SPred,Body),
 5653        ground((SPred:-Body)),
 5654	record_example(check,rand,(Pred:-Body),N1),
 5655        retract('$aleph_local'(slp_samplenum,_)),
 5656        asserta('$aleph_local'(slp_samplenum,N1)),
 5657        fail.
 5658update_gsample(_,N):-
 5659        '$aleph_local'(slp_samplenum,N),
 5660        N > 0, !,
 5661        retract('$aleph_local'(slp_samplenum,N)),
 5662        set(gsamplesize,N),
 5663        retract('$aleph_global'(atoms,atoms(rand,_))),
 5664        retract('$aleph_global'(atoms_left,atoms_left(rand,_))),
 5665        retract('$aleph_global'(last_example,last_example(rand,_))),
 5666        assert('$aleph_global'(atoms,atoms(rand,[1-N]))),
 5667        assert('$aleph_global'(atoms_left,atoms_left(rand,[1-N]))),
 5668        assert('$aleph_global'(last_example,last_example(rand,N))).
 5669update_gsample(_,_).
 5670
 5671	
 5672slprove(_,true):-
 5673	!.
 5674slprove(Mode,not(Goal)):-
 5675	slprove(Mode,Goal),
 5676	!,
 5677	fail.
 5678slprove(Mode,(Goal1,Goal2)):-
 5679	!,
 5680	slprove(Mode,Goal1),
 5681	slprove(Mode,Goal2).
 5682slprove(Mode,(Goal1;Goal2)):-
 5683	!,
 5684	slprove(Mode,Goal1);
 5685	slprove(Mode,Goal2).
 5686slprove(_,Goal):-
 5687	predicate_property(Goal,built_in), !,
 5688	Goal.
 5689slprove(stochastic,Goal):-
 5690	findall(Count/Clause,
 5691		(clause(Goal,Body),Clause=(Goal:-Body),find_count(Clause,Count)),
 5692		ClauseCounts),
 5693	renormalise(ClauseCounts,Normalised),
 5694	aleph_random(X),
 5695	rselect_clause(X,Normalised,(Goal:-Body)),
 5696	slprove(stochastic,Body).
 5697slprove(condition,Goal):-
 5698	functor(Goal,Name,Arity),
 5699	functor(Head,Name,Arity),
 5700	clause(Head,Body),
 5701	\+(\+((Head=Goal,slprove(condition,Body)))),
 5702	inc_count((Head:-Body)).
 5703
 5704renormalise(ClauseCounts,Normalised):-
 5705	sum_counts(ClauseCounts,L),
 5706	L > 0,
 5707	renormalise(ClauseCounts,L,Normalised).
 5708
 5709sum_counts([],0).
 5710sum_counts([N/_|T],C):-
 5711	sum_counts(T,C1),
 5712	C is N + C1.
 5713
 5714renormalise([],_,[]).
 5715renormalise([Count/Clause|T],L,[Prob/Clause|T1]):-
 5716	Prob is Count/L,
 5717	renormalise(T,L,T1).
 5718
 5719rselect_clause(X,[P/C|_],C):- X =< P, !.
 5720rselect_clause(X,[P/_|T],C):-
 5721	X1 is X - P,
 5722	rselect_clause(X1,T,C).
 5723
 5724
 5725find_count(Clause,N):-
 5726	copy_term(Clause,Clause1),
 5727	'$aleph_global'(slp_count,Clause1,N), !.
 5728find_count(_,1).
 5729	
 5730inc_count(Clause):-
 5731	retract('$aleph_global'(slp_count,Clause,N)), !,
 5732	N1 is N + 1,
 5733	asserta('$aleph_global'(slp_count,Clause,N1)).
 5734inc_count(Clause):-
 5735	asserta('$aleph_global'(slp_count,Clause,2)).
 5736
 5737find_posgain(PCover,P):-
 5738	'$aleph_global'(greedy,set(greedy,true)), !,
 5739	interval_count(PCover,P).
 5740find_posgain(PCover,P):-
 5741	'$aleph_global'(atoms_left,atoms_left(pos,PLeft)),
 5742	intervals_intersection(PLeft,PCover,PC),
 5743	interval_count(PC,P).
 5744
 5745
 5746%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 5747% S E A R C H  I / O 
 5748
 5749record_clause(good,Label,Clause,_):-
 5750	setting(good,true), 
 5751	setting(goodfile_stream,Stream), !,
 5752	set_output(Stream),
 5753	Label = [_,_,L|_],
 5754	aleph_writeq('$aleph_good'(L,Label,Clause)),  write('.'), nl,
 5755	flush_output(Stream),
 5756	set_output(user_output).
 5757record_clause(Flag,Label,Clause,Nodes):-
 5758	Flag \= good,
 5759	setting(recordfile_stream,Stream), !,
 5760	set_output(Stream),
 5761	show_clause(Flag,Label,Clause,Nodes),
 5762	flush_output(Stream),
 5763	set_output(user_output).
 5764record_clause(_,_,_,_).
 5765
 5766record_theory(Flag,Label,Clauses,Nodes):-
 5767	setting(recordfile_stream,Stream), !,
 5768        set_output(Stream),
 5769        show_theory(Label,Clauses,Nodes,Flag),
 5770	flush_output(Stream),
 5771        set_output(user_output).
 5772record_theory(_,_,_,_).
 5773
 5774record_theory(Flag,Label,Clauses,Nodes):-
 5775	setting(recordfile_stream,Stream), !,
 5776        set_output(Stream),
 5777        show_theory(Label,Clauses,Nodes,Flag),
 5778	flush_output(Stream),
 5779        set_output(user_output).
 5780record_theory(_,_,_,_).
 5781
 5782record_sat_example(N):-
 5783	setting(recordfile_stream,Stream), !,
 5784	set_output(Stream),
 5785	p1_message('sat'), p_message(N),
 5786	flush_output(Stream),
 5787	set_output(user_output).
 5788record_sat_example(_).
 5789
 5790record_search_stats(Clause,Nodes,Time):-
 5791	setting(recordfile_stream,Stream), !,
 5792	set_output(Stream),
 5793	p1_message('clauses constructed'), p_message(Nodes),
 5794	p1_message('search time'), p_message(Time),
 5795	p_message('best clause'),
 5796	pp_dclause(Clause),
 5797	% show(hypothesis),
 5798	flush_output(Stream),
 5799	set_output(user_output).
 5800record_search_stats(_,_,_).
 5801
 5802record_tsearch_stats(Theory,Nodes,Time):-
 5803	setting(recordfile_stream,Stream), !,
 5804        set_output(Stream),
 5805        p1_message('theories constructed'), p_message(Nodes),
 5806        p1_message('search time'), p_message(Time),
 5807        p_message('best theory'),
 5808        pp_dclauses(Theory),
 5809        % show(hypothesis),
 5810	flush_output(Stream),
 5811        set_output(user_output).
 5812record_tsearch_stats(_,_,_).
 5813
 5814record_theory(Time):-
 5815	setting(recordfile_stream,Stream), !,
 5816        set_output(Stream),
 5817        show(theory),
 5818	p1_message('time taken'), p_message(Time),
 5819        nl,
 5820        ('$aleph_global'(maxcover,set(maxcover,true))->
 5821                show(aleph,theory/5), nl,
 5822                show(aleph,max_set/4), nl,
 5823                show(aleph,rules/1);
 5824                true),
 5825	flush_output(Stream),
 5826        set_output(user_output).
 5827record_theory(_).
 5828
 5829record_features(Time):-
 5830	setting(recordfile_stream,Stream), !,
 5831        set_output(Stream),
 5832        show(features),
 5833	p1_message('time taken'), p_message(Time),
 5834	flush_output(Stream),
 5835        set_output(user_output).
 5836record_features(_).
 5837
 5838record_settings:-
 5839	setting(recordfile_stream,Stream), !,
 5840        set_output(Stream),
 5841	('$aleph_global'(os,set(os,unix)) ->
 5842		execute(date),
 5843		execute(hostname);
 5844		true),
 5845	show(settings),
 5846	flush_output(Stream),
 5847        set_output(user_output).
 5848record_settings.
 5849
 5850show_clause(Flag,Label,Clause,Nodes):-
 5851        broadcast(clause(Flag,Label,Clause,Nodes)), 
 5852	p_message('-------------------------------------'),
 5853	(Flag=good -> p_message('good clause');
 5854		(Flag=sample-> p_message('selected from sample');
 5855			p_message('found clause'))),
 5856	pp_dclause(Clause),
 5857	(setting(evalfn,Evalfn)-> true; Evalfn = coverage),
 5858	show_stats(Evalfn,Label),
 5859	p1_message('clause label'), p_message(Label),
 5860	p1_message('clauses constructed'), p_message(Nodes),
 5861	p_message('-------------------------------------').
 5862
 5863show_theory(Flag,Label,Clauses,Nodes):-
 5864        p_message('-------------------------------------'),
 5865        (Flag=good -> p_message('good theory');
 5866                (Flag=sample-> p_message('selected from sample');
 5867                        p_message('found theory'))),
 5868        pp_dclauses(Clauses),
 5869        (setting(evalfn,Evalfn)-> true; Evalfn = accuracy),
 5870        show_stats(Evalfn,Label),
 5871        p1_message('theory label'), p_message(Label),
 5872        p1_message('theories constructed'), p_message(Nodes),
 5873        p_message('-------------------------------------').
 5874
 5875update_search_stats(N,T):-
 5876	(retract('$aleph_global'(search_stats,search_stats(N0,T0))) ->
 5877			N1 is N0 + N,
 5878			T1 is T0 + T;
 5879			N1 is N,
 5880			T1 is T),
 5881	asserta('$aleph_global'(search_stats,search_stats(N1,T1))).
 5882
 5883record_total_stats:-
 5884	setting(recordfile_stream,Stream), !,
 5885	set_output(Stream),
 5886	show_total_stats,
 5887	flush_output(Stream),
 5888	set_output(user_output).
 5889record_total_stats.
 5890
 5891record_atoms_left:-
 5892	setting(recordfile_stream,Stream), !,
 5893	set_output(Stream),
 5894	show_atoms_left,
 5895	flush_output(Stream),
 5896	set_output(user_output).
 5897record_atoms_left.
 5898
 5899show_total_stats:-
 5900	'$aleph_global'(search_stats,search_stats(Nodes,_)), !,
 5901	p1_message('total clauses constructed'), p_message(Nodes).
 5902show_total_stats.
 5903	
 5904show_atoms_left:-
 5905	'$aleph_global'(atoms_left,atoms_left(pos,PLeft)),
 5906	interval_count(PLeft,NLeft),
 5907	'$aleph_global'(size,size(pos,NPos)),
 5908	'$aleph_global'(search_stats,search_stats(_,Time)),
 5909	EstTime is (Time*NLeft)/(NPos - NLeft),
 5910	p1_message('positive examples left'), p_message(NLeft),
 5911	p1_message('estimated time to finish (secs)'), p_message(EstTime), !.
 5912show_atoms_left.
 5913
 5914show_stats(Evalfn,[P,N,_,F|_]):-
 5915	((Evalfn = user; Evalfn = entropy; Evalfn = gini) ->
 5916		Value is -F;
 5917		Value is F
 5918	),
 5919	concat(['pos cover = ',P,' neg cover = ',N],Mess),
 5920	p1_message(Mess),
 5921	print_eval(Evalfn,Value).
 5922
 5923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 5924% A U T O  -- R E F I N E
 5925% 
 5926% built-in refinement operator
 5927
 5928gen_auto_refine:-
 5929	(setting(autorefine,true) -> true;
 5930		set(autorefine,true),
 5931		process_modes,
 5932		process_determs),
 5933	!.
 5934gen_auto_refine.
 5935
 5936
 5937process_modes:-
 5938	once(aleph_abolish('$aleph_link_vars'/2)),
 5939	once(aleph_abolish('$aleph_has_vars'/3)),
 5940	once(aleph_abolish('$aleph_has_ovar'/4)),
 5941	once(aleph_abolish('$aleph_has_ivar'/4)),
 5942	'$aleph_global'(modeb,modeb(_,Mode)),
 5943	process_mode(Mode),
 5944	fail.
 5945process_modes:-
 5946	'$aleph_global'(determination,determination(Name/Arity,_)),
 5947	find_mode(modeh,Name/Arity,Mode),
 5948	split_args(Mode,Mode,I,O,_),
 5949	functor(Lit,Name,Arity),
 5950	copy_modeterms(Mode,Lit,Arity),
 5951	add_ivars(Lit,I),
 5952	add_ovars(Lit,O),
 5953	add_vars(Lit,I,O),
 5954	fail.
 5955process_modes.
 5956
 5957process_determs:-
 5958	once(aleph_abolish('$aleph_determination'/2)),
 5959	'$aleph_global'(determination,determination(Name/Arity,Name1/Arity1)),
 5960	functor(Pred,Name1,Arity1),
 5961	find_mode(modeb,Name1/Arity1,Mode),
 5962	copy_modeterms(Mode,Pred,Arity1),
 5963	Determ = '$aleph_determination'(Name/Arity,Pred),
 5964	(Determ -> true; assert(Determ)),
 5965	fail.
 5966process_determs.
 5967
 5968process_mode(Mode):-
 5969	functor(Mode,Name,Arity),
 5970	split_args(Mode,Mode,I,O,C),
 5971	functor(Lit,Name,Arity),
 5972	copy_modeterms(Mode,Lit,Arity),
 5973	add_ioc_links(Lit,I,O,C),
 5974	add_ovars(Lit,O),
 5975	add_vars(Lit,I,O).
 5976
 5977add_ioc_links(Lit,I,O,C):-
 5978	Clause = ('$aleph_link_vars'(Lit,Lits):-
 5979			var_types(Lits,VT),
 5980			Body),
 5981	get_o_links(O,Lit,VT,true,OGoals),
 5982	get_i_links(I,Lit,VT,OGoals,IOGoals),
 5983	get_c_links(C,Lit,IOGoals,Body),
 5984	assert(Clause).
 5985
 5986add_ovars(Lit,O):-
 5987	aleph_member(Pos/Type,O),
 5988	tparg(Pos,Lit,V),
 5989	('$aleph_has_ovar'(Lit,V,Type,Pos)->true;
 5990		assert('$aleph_has_ovar'(Lit,V,Type,Pos))),
 5991	fail.
 5992add_ovars(_,_).
 5993
 5994add_ivars(Lit,I):-
 5995	aleph_member(Pos/Type,I),
 5996	tparg(Pos,Lit,V),
 5997	('$aleph_has_ivar'(Lit,V,Type,Pos)->true;
 5998		assert('$aleph_has_ivar'(Lit,V,Type,Pos))),
 5999	fail.
 6000add_ivars(_,_).
 6001
 6002add_vars(Lit,I,O):-
 6003        get_var_types(I,Lit,IVarTypes),
 6004        get_var_types(O,Lit,OVarTypes),
 6005        ('$aleph_has_vars'(Lit,IVarTypes,OVarTypes) -> true;
 6006        	assert('$aleph_has_vars'(Lit,IVarTypes,OVarTypes))).
 6007
 6008get_var_types([],_,[]).
 6009get_var_types([Pos/Type|PlaceTypes],Lit,[Var/Type|Rest]):-
 6010        tparg(Pos,Lit,Var),
 6011        get_var_types(PlaceTypes,Lit,Rest).
 6012
 6013get_o_links([],_,_,Goals,Goals).
 6014get_o_links([Pos/Type|T],Lit,VarTypes,GoalsSoFar,Goals):-
 6015	tparg(Pos,Lit,V),
 6016	Goal = (aleph_output_var(V,Type,VarTypes);
 6017		aleph_output_var(V,Type,Lit,Pos)),
 6018	prefix_lits((Goal),GoalsSoFar,G1),
 6019	get_o_links(T,Lit,VarTypes,G1,Goals).
 6020
 6021
 6022get_i_links([],_,_,Goals,Goals).
 6023get_i_links([Pos/Type|T],Lit,VarTypes,GoalsSoFar,Goals):-
 6024	tparg(Pos,Lit,V),
 6025	Goal = aleph_input_var(V,Type,VarTypes),
 6026	prefix_lits((Goal),GoalsSoFar,G1),
 6027	get_i_links(T,Lit,VarTypes,G1,Goals).
 6028
 6029get_c_links([],_,Goals,Goals).
 6030get_c_links([Pos/Type|T],Lit,GoalsSoFar,Goals):-
 6031	tparg(Pos,Lit,V),
 6032	TypeFact =.. [Type,C],
 6033	Goal = (TypeFact,V=C),
 6034	prefix_lits((Goal),GoalsSoFar,G1),
 6035	get_c_links(T,Lit,G1,Goals).
 6036	
 6037aleph_input_var(Var,Type,VarTypes):-
 6038        aleph_member(Var/Type1,VarTypes),
 6039	nonvar(Type1),
 6040	Type = Type1.
 6041
 6042aleph_output_var(Var,Type,VarTypes):-
 6043        aleph_member(Var/Type1,VarTypes),
 6044	nonvar(Type1),
 6045	Type = Type1.
 6046aleph_output_var(_,_,_).
 6047
 6048aleph_output_var(Var,Type,Lit,ThisPos):-
 6049	'$aleph_has_ovar'(Lit,Var,Type,Pos),
 6050	Pos @< ThisPos.
 6051
 6052var_types([Head|Body],VarTypes):-
 6053        hvar_types(Head,HVarTypes),
 6054        bvar_types(Body,HVarTypes,BVarTypes),
 6055        aleph_append(BVarTypes,HVarTypes,VarTypesList),
 6056        sort(VarTypesList,VarTypes).
 6057
 6058hvar_types(Head,HVarTypes):-
 6059	'$aleph_has_vars'(Head,IVarTypes,OVarTypes),
 6060        aleph_append(IVarTypes,OVarTypes,HVarTypes).
 6061
 6062bvar_types([],V,V).
 6063bvar_types([Lit|Lits],VTSoFar,BVarTypes):-
 6064	'$aleph_has_vars'(Lit,IVarTypes,OVarTypes),
 6065        consistent_vartypes(IVarTypes,VTSoFar),
 6066        \+ inconsistent_vartypes(OVarTypes,VTSoFar),
 6067        aleph_append(OVarTypes,VTSoFar,VT1),
 6068        bvar_types(Lits,VT1,BVarTypes).
 6069
 6070consistent_vartypes([],_).
 6071consistent_vartypes([Var/Type|VarTypes],VTSoFar):-
 6072        aleph_member2(Var/Type,VTSoFar),
 6073        consistent_vartypes(VarTypes,VTSoFar).
 6074                                                                                
 6075inconsistent_vartypes([Var/Type|_],VTSoFar):-
 6076        aleph_member(Var1/Type1,VTSoFar),
 6077        Var == Var1,
 6078        Type \== Type1, !.
 6079inconsistent_vartypes([_|VarTypes],VTSoFar):-
 6080        inconsistent_vartypes(VarTypes,VTSoFar).
 6081
 6082
 6083aleph_get_hlit(Name/Arity,Head):-
 6084	functor(Head,Name,Arity),
 6085	find_mode(modeh,Name/Arity,Mode),
 6086	once(split_args(Mode,Mode,_,_,C)),
 6087	copy_modeterms(Mode,Head,Arity),
 6088	get_c_links(C,Head,true,Equalities),
 6089	Equalities.
 6090
 6091aleph_get_lit(Lit,[H|Lits]):-
 6092	functor(H,Name,Arity),
 6093	aleph_get_lit(Lit,Name/Arity),
 6094	'$aleph_link_vars'(Lit,[H|Lits]),
 6095	\+(aleph_member2(Lit,[H|Lits])).
 6096
 6097aleph_get_lit(Lit,Target):-
 6098	'$aleph_determination'(Target,Lit).
 6099
 6100% aleph_mode_linked(+Lits)
 6101% checks to see if a sequence of literals are within mode language
 6102% using information compiled by process_modes/0
 6103aleph_mode_linked([H|B]):-
 6104	aleph_mode_linked(B,[H]).
 6105
 6106aleph_mode_linked([],_):- !.
 6107aleph_mode_linked([Lit|Lits],LitsSoFar):-
 6108	'$aleph_link_vars'(Lit,LitsSoFar),
 6109	aleph_append([Lit],LitsSoFar,L1),
 6110	aleph_mode_linked(Lits,L1).
 6111
 6112auto_refine(false,Head):-
 6113	example_saturated(Example), 
 6114	functor(Example,Name,Arity),
 6115        aleph_get_hlit(Name/Arity,Head),
 6116	Head \== false.
 6117auto_refine(false,Head):-
 6118        '$aleph_global'(modeh,modeh(_,Pred)),
 6119	functor(Pred,Name,Arity),
 6120        aleph_get_hlit(Name/Arity,Head),
 6121	Head \== false.
 6122auto_refine((H:-B),(H1:-B1)):-
 6123        !,
 6124        goals_to_list((H,B),LitList),
 6125        setting(clauselength,L),
 6126        length(LitList,ClauseLength),
 6127        ClauseLength < L,
 6128        aleph_get_lit(Lit,LitList),
 6129        aleph_append([Lit],LitList,LitList1),
 6130        list_to_goals(LitList1,(H1,B1)),
 6131	\+(prune((H1:-B1))),
 6132	\+(tautology((H1:-B1))),
 6133	(setting(language,Lang) ->
 6134		lang_ok(Lang,H1,B1);
 6135		true),
 6136	(setting(newvars,NewVars) ->
 6137		newvars_ok(NewVars,H1,B1);
 6138		true).
 6139auto_refine(Head,Clause):-
 6140        auto_refine((Head:-true),Clause).
 6141
 6142% refinement with lookahead
 6143auto_refine(1,Clause1,Clause2):-
 6144	!,
 6145	auto_refine(Clause1,Clause2).
 6146auto_refine(L,Clause1,Clause2):-
 6147	L1 is L - 1, 
 6148	auto_refine(L1,Clause1,Clause),
 6149	(Clause2 = Clause;
 6150		auto_refine(Clause,Clause2)).
 6151
 6152auto_extend((H:-B),Lit,(H1:-B1)):-
 6153        !,
 6154        goals_to_list((H,B),LitList),
 6155        setting(clauselength,L),
 6156        length(LitList,ClauseLength),
 6157        ClauseLength < L,
 6158        aleph_get_lit(Lit,LitList),
 6159        aleph_append([Lit],LitList,LitList1),
 6160        list_to_goals(LitList1,(H1,B1)),
 6161	(setting(language,Lang) ->
 6162		lang_ok(Lang,H1,B1);
 6163		true),
 6164	(setting(newvars,NewVars) ->
 6165		newvars_ok(NewVars,H1,B1);
 6166		true),
 6167	\+(tautology((H1:-B1))),
 6168	\+(prune((H1:-B1))).
 6169
 6170tautology((false:-Body)):-
 6171	!,
 6172	in(Body,L1,Rest),
 6173	in(Rest,not(L2)),
 6174	L1 == L2.
 6175tautology((Head:-Body)):-
 6176	in(Body,Lit),
 6177	Head == Lit, !.
 6178
 6179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 6180% A U T O -- M O D E   
 6181
 6182% automatic inference of mode declarations given a set of
 6183% determinations. The procedure works in two parts: (i) finding
 6184% equivalence classes of types; and (ii) finding an input/output
 6185% assignment.
 6186% 
 6187% Finding equivalence classes of types is similar to
 6188% the work of McCreath and Sharma, Proc of the 8th Australian
 6189% Joint Conf on AI pages 75-82, 1995. However, unlike there
 6190% types in the same equivalence class are given the same name only if
 6191% they "overlap" significantly (the overlap of type1 with type2
 6192% is the proportion of elements of type1 that are also elements of type2). 
 6193% Significantly here means an overlap at least some threshold
 6194% T (set using typeoverlap, with default 0.95).
 6195% Since this may not be perfect, modes are also produced
 6196% for equality statements that re-introduce co-referencing amongst
 6197% differently named types in the same equivalence class.
 6198% The user has to however explicitly include a determination declaration for
 6199% the equality predicate.
 6200% 
 6201% The i/o assignment is not straightforward, as we may be dealing
 6202% with non-functional definitions. The assignment sought here is one
 6203% that maximises the number of input args as this gives the
 6204% largest bottom clause. This assignment is
 6205% is sought by means of a search procedure over mode sequences.
 6206% Suppose we have a mode sequence M = <m1,m2,..m{i-1}> that uses the types T.
 6207% An argument of type t in mode m{i} is an input iff t overlaps
 6208% significantly (used in the same sense as earlier) with some type in T.
 6209% Otherwise the argument is an output.
 6210% The utility of each mode sequence M is f(M) = g(M) + h(M) where
 6211% g(M) is the number of input args in M; and h(M) is a (lower) estimate
 6212% of the number of input args in any mode sequence of which M is a prefix.
 6213% The search strategy adopted is a simple hill-climbing one.
 6214%
 6215% All very complicated: there must be a simpler approach.
 6216% Requires generative background predicates.
 6217
 6218search_modes:-
 6219	'$aleph_global'(targetpred,targetpred(N/A)),
 6220	findall(N1/A1,determinations(N/A,N1/A1),L),
 6221	number_types([N/A|L],0,TypedPreds,Last),
 6222	get_type_elements(TypedPreds),
 6223	interval_to_list(1-Last,Types),
 6224	get_type_equivalences(Types,Equiv1),
 6225	merge_equivalence_classes(Equiv1,Equiv),
 6226	store_type_equivalences(Equiv),
 6227	setting(typeoverlap,Thresh),
 6228	infer_modes(TypedPreds,Thresh,Types,Modes),
 6229	infer_equalities(EqModes),
 6230	Modes = [_|BodyModes],
 6231	infer_negations(BodyModes,NegModes),
 6232	(setting(updateback,Update) -> true; Update = true),
 6233	p_message('found modes'),
 6234	add_inferred_modes(Modes,Update),
 6235	add_inferred_modes(EqModes,Update),
 6236	add_inferred_modes(NegModes,Update),
 6237	fail.
 6238search_modes.
 6239
 6240number_types([],Last,[],Last).
 6241number_types([N/A|T],L0,[Pred|T1],L1):-
 6242	functor(Pred,N,A),
 6243	L is L0 + A,
 6244	number_types(A,L,Pred),
 6245	number_types(T,L,T1,L1).
 6246
 6247number_types(0,_,_):- !.
 6248number_types(A,N,Pred):-
 6249	arg(A,Pred,N),
 6250	A1 is A - 1,
 6251	N1 is N - 1,
 6252	number_types(A1,N1,Pred).
 6253
 6254get_type_elements([]).
 6255get_type_elements([Pred|Preds]):-
 6256	functor(Pred,Name,Arity),
 6257	functor(Template,Name,Arity),
 6258	interval_to_list(1-Arity,AL),
 6259	get_type_elements(example(_,_,Template),Template,Pred,AL),
 6260	get_type_elements(Template,Template,Pred,AL),
 6261	get_type_elements(Preds).
 6262
 6263get_type_elements(Fact,Template,Pred,AL):-
 6264	aleph_member(Arg,AL),
 6265	findall(Val,(Fact,ground(Fact),arg(Arg,Template,Val)),Vals),
 6266	arg(Arg,Pred,Type),
 6267	sort(Vals,SVals),
 6268	(retract('$aleph_search'(modes,type(Type,_,OtherVals))) ->
 6269		aleph_ord_union(SVals,OtherVals,ArgVals);
 6270		ArgVals = SVals),
 6271	length(ArgVals,N),
 6272	asserta('$aleph_search'(modes,type(Type,N,ArgVals))),
 6273	fail.
 6274get_type_elements(_,_,_,_).
 6275
 6276get_type_equivalences([],[]).
 6277get_type_equivalences([First|Rest],[Class|Classes]):-
 6278	get_type_equivalence(Rest,[First],Class,Left),
 6279	get_type_equivalences(Left,Classes).
 6280
 6281get_type_equivalence([],Class1,Class,[]):-
 6282	sort(Class1,Class).
 6283get_type_equivalence([Type|Rest],Class1,Class,Left):-
 6284	type_equivalent(Class1,Type), !,
 6285	get_type_equivalence(Rest,[Type|Class1],Class,Left).
 6286get_type_equivalence([Type|Rest],Class1,Class,[Type|Left]):-
 6287	get_type_equivalence(Rest,Class1,Class,Left).
 6288
 6289merge_equivalence_classes([Class],[Class]):- !.
 6290merge_equivalence_classes(Classes1,Classes2):-
 6291        aleph_delete(Class1,Classes1,Left),
 6292        aleph_delete(Class2,Left,Left1),
 6293        class_equivalent(Class1,Class2), !,
 6294        aleph_ord_union(Class1,Class2,NewClass),
 6295        merge_equivalence_classes([NewClass|Left1],Classes2).
 6296merge_equivalence_classes(Classes,Classes).
 6297
 6298class_equivalent(Class1,Class2):-
 6299        aleph_member(Type1,Class1),
 6300        type_equivalent(Class2,Type1), !.
 6301
 6302type_equivalent([T1|_],T2):-
 6303	'$aleph_search'(modes,type(T1,_,E1)),
 6304	'$aleph_search'(modes,type(T2,_,E2)),
 6305	intersects(E1,E2), !.
 6306type_equivalent([_|T],T2):-
 6307	type_equivalent(T,T2).
 6308
 6309store_type_equivalences([]).
 6310store_type_equivalences([[CType|Class]|Classes]):-
 6311	length([CType|Class],N),
 6312	store_type_equivalence([CType|Class],CType,N),
 6313	store_type_equivalences(Classes).
 6314
 6315store_type_equivalence([],_,_).
 6316store_type_equivalence([Type|Types],CType,Neq):-
 6317	retract('$aleph_search'(modes,type(Type,N,Elements))),
 6318	store_type_overlaps(Types,Type,Elements,N),
 6319	asserta('$aleph_search'(modes,type(Type,CType,Neq,N,Elements))),
 6320	store_type_equivalence(Types,CType,Neq).
 6321
 6322store_type_overlaps([],_,_,_).
 6323store_type_overlaps([T1|Types],T,E,N):-
 6324	'$aleph_search'(modes,type(T1,N1,E1)),
 6325	aleph_ord_intersection(E1,E,Int),
 6326	length(Int,NInt),
 6327	O is NInt/N,
 6328	O1 is NInt/N1,
 6329	asserta('$aleph_search'(modes,typeoverlap(T,T1,O,O1))),
 6330	store_type_overlaps(Types,T,E,N).
 6331
 6332infer_modes([Head|Rest],Thresh,Types,[Head1|Rest1]):-
 6333	infer_mode(Head,Thresh,head,[],Head1,Seen),
 6334	aleph_delete_list(Seen,Types,TypesLeft),
 6335	infer_ordered_modes(Rest,Thresh,body,Seen,TypesLeft,Rest1).
 6336
 6337infer_ordered_modes([],_,_,_,_,[]):- !.
 6338infer_ordered_modes(L,Thresh,Loc,Seen,Left,[Mode|Rest]):-
 6339	score_modes(L,Thresh,Seen,Left,ScoredPreds),
 6340	keysort(ScoredPreds,[_-Pred|_]), 
 6341	infer_mode(Pred,Thresh,Loc,Seen,Mode,Seen1),
 6342	aleph_delete(Pred,L,L1),
 6343	aleph_delete_list(Seen1,Left,Left1),
 6344	infer_ordered_modes(L1,Thresh,Loc,Seen1,Left1,Rest).
 6345
 6346score_modes([],_,_,_,[]).
 6347score_modes([Pred|Preds],Thresh,Seen,Left,[Cost-Pred|Rest]):-
 6348	Pred =.. [_|Types],
 6349	evaluate_backward(Types,Thresh,Seen,G),
 6350	aleph_delete_list(Types,Left,Left1),
 6351	estimate_forward(Seen,Thresh,Left1,H0),
 6352	estimate_forward(Types,Thresh,Left1,H1),
 6353	Diff is H1 - H0,
 6354	(Diff < 0 -> H is 0; H is Diff),
 6355	Cost is -(G + H),
 6356	score_modes(Preds,Thresh,Seen,Left,Rest).
 6357
 6358evaluate_backward([],_,_,0.0).
 6359evaluate_backward([Type|Types],Thresh,Seen,Score):-
 6360	best_overlap(Seen,Type,_,Overlap),
 6361	(Overlap >= Thresh -> Score1 = 1.0; Score1 = 0.0),
 6362	evaluate_backward(Types,Thresh,Seen,Score2),
 6363	Score is Score1 + Score2.
 6364
 6365estimate_forward([],_,_,0.0).
 6366estimate_forward([Type|Types],Thresh,Left,Score):-
 6367        estimate_forward1(Left,Thresh,Type,S1),
 6368        estimate_forward(Types,Thresh,Left,S2),
 6369        Score is S1 + S2.
 6370
 6371estimate_forward1([],_,_,0.0).
 6372estimate_forward1([T1|Types],Thresh,T,Score):-
 6373        type_overlap(T1,T,O1),
 6374	(O1 >= Thresh -> S1 is 1.0; S1 is 0.0),
 6375        estimate_forward1(Types,Thresh,T,S2),
 6376        Score is S1 + S2.
 6377
 6378infer_mode(Pred,Thresh,Loc,Seen0,InferredMode,Seen):-
 6379	Pred =.. [Name|Types],
 6380	infer_mode1(Types,Thresh,Loc,Seen0,Modes),
 6381	Mode =.. [Name|Modes],
 6382	length(Types,Arity),
 6383	('$aleph_global'(targetpred,targetpred(Name/Arity)) ->
 6384		InferredMode = modeh(*,Mode);
 6385		InferredMode = mode(*,Mode)),
 6386	aleph_ord_union(Seen0,Types,Seen).
 6387
 6388infer_mode1([],_,_,_,[]).
 6389infer_mode1([Type|Types],Thresh,Loc,Seen,[Mode|Modes]):-
 6390	best_overlap(Seen,Type,Best,Overlap),
 6391	(Overlap >= Thresh ->
 6392		'$aleph_search'(modes,typemapped(Best,_,NewType)),
 6393		asserta('$aleph_search'(modes,typemapped(Type,Best,NewType))),
 6394		concat([type,NewType],Name),
 6395		Mode = +Name;
 6396		(Overlap > 0.0 ->
 6397			asserta('$aleph_search'(modes,typemapped(Type,Best,Type)));
 6398			asserta('$aleph_search'(modes,typemapped(Type,Type,Type)))),
 6399		concat([type,Type],Name),
 6400		(Loc = head -> Mode = +Name; Mode = -Name)
 6401	),
 6402	infer_mode1(Types,Thresh,Loc,Seen,Modes).
 6403
 6404
 6405best_overlap([T1],T,T1,O):-
 6406	!,
 6407	type_overlap(T,T1,O).
 6408best_overlap([T1|Types],T,Best,O):-
 6409	type_overlap(T,T1,O1),
 6410	best_overlap(Types,T,T2,O2),
 6411	(O2 > O1 -> O is O2, Best = T2; O is O1, Best = T1).
 6412best_overlap([],T,T,0.0).
 6413
 6414type_overlap(T,T1,O):-
 6415	T > T1, !,
 6416	('$aleph_search'(modes,typeoverlap(T1,T,_,O)) -> true; O = 0.0).
 6417type_overlap(T,T1,O):-
 6418	('$aleph_search'(modes,typeoverlap(T,T1,O,_)) -> true; O = 0.0).
 6419
 6420
 6421infer_equalities(EqModes):-
 6422	findall(mode(1,(Eq)),(pairwise_equality(Eq);grounding_equality(Eq)),
 6423		EqL),
 6424	sort(EqL,EqModes).
 6425
 6426infer_negations([],[]).
 6427infer_negations([mode(_,Pred)|Modes],NegModes):-
 6428	Pred =.. [_|Args],
 6429	aleph_member1(-_,Args), !,
 6430	infer_negations(Modes,NegModes).
 6431infer_negations([mode(_,Pred)|Modes],[mode(1,not(Pred))|NegModes]):-
 6432	infer_negations(Modes,NegModes).
 6433	
 6434
 6435pairwise_equality((+N1 = +N2)):-
 6436	'$aleph_search'(modes,typemapped(_,Best,T1)),
 6437	'$aleph_search'(modes,typemapped(Best,_,T2)),
 6438	T1 \== T2,
 6439	concat([type,T1],N1),
 6440	concat([type,T2],N2).
 6441grounding_equality((+N1 = #N1)):-
 6442	'$aleph_search'(modes,typemapped(T1,_,T1)),
 6443	concat([type,T1],N1).
 6444
 6445add_inferred_modes([],_).
 6446add_inferred_modes([Mode|Modes],Flag):-
 6447	write(Mode), nl,
 6448	(Flag = true -> Mode; true),
 6449	add_inferred_modes(Modes,Flag).
 6450	
 6451
 6452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 6453% S T O C H A S T I C   S E A R C H
 6454 
 6455% sample_clauses(+N,-Clauses)
 6456%	return sample of at most N legal clauses from hypothesis space
 6457%	If a bottom clause exists then
 6458%		Each clause is drawn randomly. The length of the clause is
 6459%		determined by:
 6460%			(a) user-specified distribution over clauselengths
 6461%			    using set(clauselength_distribution,Distribution);
 6462%			    Distribution is a list of the form p1-1, p2-2,...
 6463%			    specifying that clauselength 1 has prob p1, etc.
 6464%			    Note: sum pi must = 1. This is not checked; or
 6465%			(b) uniform distribution over all legal clauses.
 6466%			    (if clauselength_distribution is not set)
 6467%			    this uses a Monte-Carlo estimate of the number of
 6468%			    legal clauses in the hypothesis space
 6469%	If a bottom clause does not exist, then legal clauses are constructed
 6470%	using the mode declarations. Only option (a) is allowed. If
 6471%	clauselength_distribution is not set, then a uniform distribution over
 6472%	lengths is assumed.
 6473%	Each element of Clauses is of the form L-[E,T,Lits,Clause] where
 6474%	L is the clauselength; E,T are example number and type (pos, neg) used
 6475%	to build the bottom clause; Lits contains the literal numbers in the
 6476%	bottom clause for Clause. If no bottom clause then E,T = 0 and Lits = []
 6477% 	Clauses is in ascending order of clause length
 6478sample_clauses(N,Clauses):-
 6479	setting(construct_bottom,Bottom),
 6480	sample_nclauses(Bottom,N,Clauses).
 6481
 6482sample_nclauses(false,N,Clauses):-
 6483	!,
 6484	gen_auto_refine,
 6485	(setting(clauselength_distribution,D) -> true;
 6486		setting(clauselength,CL),
 6487		Uniform is 1.0/CL,
 6488		distrib(1-CL,Uniform,D)),
 6489	sample_nclauses_using_modes(N,D,CList),
 6490	remove_alpha_variants(CList,CList1),
 6491	keysort(CList1,Clauses).
 6492sample_nclauses(_,N,Clauses):-
 6493	retractall('$aleph_sat'(random,rselect(_))),
 6494	('$aleph_sat'(example,example(_,_)) -> true; rsat),
 6495	setting(clauselength,CL),
 6496	(setting(clauselength_distribution,Universe) ->
 6497		Sample is N;
 6498		estimate_numbers(CL,1,400,Universe),
 6499		(N > Universe -> Sample is Universe; Sample is N)),
 6500	get_clause_sample(Sample,Universe,CL,CList),
 6501	keysort(CList,Clauses).
 6502
 6503% sample_nclauses_using_modes(+N,+D,-Clauses)
 6504% 	get upto N legal clauses using mode declarations
 6505%	and distribution D over clauselengths
 6506
 6507sample_nclauses_using_modes(0,_,[]):- !.
 6508sample_nclauses_using_modes(N,D,[Clause|Rest]):-
 6509	legal_clause_using_modes(100,D,Clause),
 6510	N1 is N - 1,
 6511	sample_nclauses_using_modes(N1,D,Rest).
 6512
 6513% legal_clause_using_modes(+N,+D,-Clause)
 6514%	make at most N attempts to obtain a legal clause Clause
 6515%	from mode language using distribution D over clauselengths
 6516%	if all N attempts fail, then just return most general clause
 6517legal_clause_using_modes(N,D,L-[0,0,[],Clause]):-
 6518	N > 0,
 6519	sample_clause_using_modes(D,L,Clause),
 6520	\+(prune(Clause)),
 6521	split_clause(Clause,Head,Body),
 6522	(setting(language,Lang) ->
 6523        	lang_ok(Lang,Head,Body);
 6524		true),
 6525	(setting(newvars,NewVars) ->
 6526		newvars_ok(NewVars,Head,Body);
 6527		true),
 6528	!.
 6529legal_clause_using_modes(N,D,Clause):-
 6530	N > 1,
 6531	N1 is N - 1,
 6532	legal_clause_using_modes(N1,D,Clause), !.
 6533legal_clause_using_modes(_,_,1-[0,0,[],Clause]):-
 6534	sample_clause_using_modes([1.0-1],1,Clause).
 6535
 6536sample_clause_using_modes(D,L,Clause):-
 6537	findall(H,auto_refine(false,H),HL),
 6538	HL \= [],
 6539	random_select(Head,HL,_),
 6540	draw_element(D,L),
 6541	(L = 1 -> Clause = Head;
 6542		L1 is L - 1,
 6543		sample_clause_using_modes(L1,Head,Clause)).
 6544
 6545sample_clause_using_modes(N,ClauseSoFar,Clause):-
 6546	findall(C,auto_refine(ClauseSoFar,C),CL),
 6547	CL \= [], !,
 6548	(N = 1 -> random_select(Clause,CL,_);
 6549		random_select(C1,CL,_),
 6550		N1 is N - 1,
 6551		sample_clause_using_modes(N1,C1,Clause)).
 6552sample_clause_using_modes(_,Clause,Clause).
 6553
 6554
 6555% get_clause_sample(+N,+U,+CL,-Clauses)
 6556% 	get upto N legal clauses of at most length CL drawn from universe U
 6557%	U is either the total number of legal clauses
 6558%		or a distribution over clauselengths
 6559%	the clauses are constructed by drawing randomly from bottom
 6560get_clause_sample(0,_,_,[]):- !.
 6561get_clause_sample(N,Universe,CL,[L-[E,T,C1,C]|Clauses]):-
 6562        (number(Universe) ->
 6563		get_rrandom(Universe,ClauseNum),
 6564		num_to_length(ClauseNum,CL,L),
 6565		UpperLim is CL;
 6566		draw_element(Universe,L),
 6567		UpperLim is L),
 6568	draw_legalclause_wo_repl(L,UpperLim,C,C1), !,
 6569	'$aleph_sat'(example,example(E,T)),
 6570	N1 is N - 1,
 6571	get_clause_sample(N1,Universe,CL,Clauses).
 6572get_clause_sample(N,Universe,CL,Clauses):-
 6573	N1 is N - 1,
 6574	get_clause_sample(N1,Universe,CL,Clauses).
 6575
 6576% draw_legalclause_wo_repl(+L,+CL,-C,-Lits)
 6577%	randomly draw without replacement a legal clause of length >= L and =< CL 
 6578%	also returns literals from bottom used to construct clause
 6579draw_legalclause_wo_repl(L,CL,C,C1):-
 6580	L =< CL,
 6581	randclause_wo_repl(L,C,legal,C1), !.
 6582draw_legalclause_wo_repl(L,CL,C,C1):-
 6583	L < CL,
 6584	L1 is L + 1,
 6585	draw_legalclause_wo_repl(L1, CL,C,C1).
 6586
 6587% estimate_clauselength_distribution(+L,+T,+K,-D)
 6588%	for each clauselength l <= L, estimate the probability of
 6589%	drawing a good clause
 6590%	here, a ``good clause'' is one that is in the top K-percentile of clauses
 6591%	estimation is by Monte Carlo using at most T trials
 6592%	probabilities are normalised to add to 1
 6593estimate_clauselength_distribution(L,T,K,D):-	
 6594	'$aleph_sat'(example,example(Type,Example)),
 6595	'$aleph_sat'(random,clauselength_distribution(Type,Example,L,T,K,D)), !.
 6596estimate_clauselength_distribution(L,T,K,D):-	
 6597	setting(evalfn,Evalfn),
 6598	estimate_clauselength_scores(L,T,Evalfn,[],S),
 6599	select_good_clauses(S,K,Good),
 6600	estimate_frequency(L,Good,Freq),
 6601	normalise_distribution(Freq,D),
 6602	('$aleph_sat'(example,example(Type,Example)) ->
 6603		asserta('$aleph_sat'(random,clauselength_distribution(Type,
 6604						Example,L,T,K,D)));
 6605		true).
 6606
 6607estimate_clauselength_scores(0,_,_,S,S):- !.
 6608estimate_clauselength_scores(L,T,Evalfn,S1,S):-
 6609	set(clauselength_distribution,[1.0-L]),
 6610	p1_message('Estimate scores of clauses with length'), p_message(L),
 6611	sample_clauses(T,Clauses),
 6612	estimate_scores(Clauses,Evalfn,S1,S2),
 6613	L1 is L - 1,
 6614	estimate_clauselength_scores(L1,T,Evalfn,S2,S).
 6615
 6616estimate_scores([],_,S,S):- !.
 6617estimate_scores([L-[_,_,_,C]|Rest],Evalfn,S1,S):-
 6618	label_create(C,Label),
 6619	extract_count(pos,Label,PC),
 6620	extract_count(neg,Label,NC),
 6621	complete_label(Evalfn,C,[PC,NC,L],[_,_,_,Val|_]),
 6622	estimate_scores(Rest,Evalfn,[-Val-L|S1],S).
 6623	
 6624% ``good'' clauses are defined to be those in the top K-percentile
 6625%	policy on ties is to include them
 6626select_good_clauses(S,K,Good):-
 6627	keysort(S,S1),
 6628	length(S1,Total),
 6629	N is integer(K*Total/100),
 6630	select_good_clauses(S1,N,[],Good).
 6631
 6632select_good_clauses([],_,Good,Good):- !.
 6633select_good_clauses(_,N,Good,Good):- N =< 0, !.
 6634select_good_clauses([Score-X|T],N,GoodSoFar,Good):-
 6635	select_good_clauses(T,Score,N,[Score-X|GoodSoFar],N0,Good1,T1),
 6636	N1 is N0 - 1,
 6637	select_good_clauses(T1,N1,Good1,Good).
 6638
 6639select_good_clauses([],_,N,G,N,G,[]):- !.
 6640select_good_clauses([Score-X|T],Score,N,GoodSoFar,N0,Good1,T1):-
 6641	!,
 6642	N1 is N - 1,
 6643	select_good_clauses(T,Score,N1,[Score-X|GoodSoFar],N0,Good1,T1).
 6644select_good_clauses(L,_,N,G,N,G,L).
 6645
 6646estimate_frequency(0,_,[]).
 6647estimate_frequency(L,Good,[N-L|T]):-
 6648	count_frequency(Good,L,N),
 6649	L1 is L - 1,
 6650	estimate_frequency(L1,Good,T).
 6651
 6652count_frequency([],_,0).
 6653count_frequency([Entry|T],X,N):-
 6654	count_frequency(T,X,N1),
 6655	(Entry = _-X -> N is N1 + 1; N is N1).
 6656
 6657% 	estimate total number of legal clauses in space
 6658%	bounded by bot
 6659estimate_numbers(Total):- 
 6660	('$aleph_sat'(example,example(_,_)) -> true; rsat),
 6661	setting(clauselength,CL),
 6662	estimate_numbers(CL,1,400,Total).
 6663
 6664% estimate_numbers(+L,+Trials,+Sample,-T)
 6665% 	estimate total number of legal clauses of length <= L in space
 6666%	bounded by bot
 6667%	estimated number is cached for future use
 6668%	estimation is by Monte Carlo, averaged over Trials trials
 6669%	with given sample size
 6670estimate_numbers(L,Trials,Sample,Total):-
 6671	'$aleph_sat'(example,example(Type,Example)),
 6672	'$aleph_sat'(random,sample(Type,Example,L,Trials,Sample)),
 6673	'$aleph_sat'(random,hypothesis_space(Total)), !.
 6674estimate_numbers(L,Trials,Sample,Total):-
 6675	retractall('$aleph_sat'(random,sample(_,_,_,_,_))),
 6676	retractall('$aleph_sat'(random,hypothesis_space(_))),
 6677	estimate_numbers(L,Trials,Sample,0,Total),
 6678	asserta('$aleph_sat'(random,hypothesis_space(Total))),
 6679	'$aleph_sat'(example,example(Type,Example)),
 6680	asserta('$aleph_sat'(random,sample(Type,Example,L,Trials,Sample))).
 6681
 6682% estimate_numbers(+L,+Trials,+Sample,+TotalSoFar,-Total)
 6683%	estimate the number of legal clauses of length <= L
 6684%	estimated number of legal clauses at each length are cached for future use
 6685%	TotalSoFar is an accumulator of the number legal clauses so far
 6686%	Total is the cumulative total of the number of legal clauses
 6687estimate_numbers(0,_,_,T,T):- !.
 6688estimate_numbers(L,Trials,Sample,TotalSoFar,T):-
 6689	retractall('$aleph_sat'(random,number_of_clauses(L,_))),
 6690	estimate_number(Trials,Sample,L,T0),
 6691	asserta('$aleph_sat'(random,number_of_clauses(L,T0))),
 6692	L1 is L - 1,
 6693	T1 is T0 + TotalSoFar,
 6694	estimate_numbers(L1,Trials,Sample,T1,T).
 6695
 6696% estimate_number(+T,+S,+L,-N)
 6697%	monte carlo estimate of number of legal clauses of length L
 6698%	estimate formed from average over T trials with sample S
 6699estimate_number(_,_,L,0):-
 6700        '$aleph_sat'(lastlit,Last),
 6701        Last < L, !.   
 6702estimate_number(T,S,L,N):-
 6703	T > 0,
 6704	p1_message('Estimate legal clauses with length'), p_message(L),
 6705	estimate_number(T,S,0,L,Total),
 6706	N is float(Total/T),
 6707	concat(['trials=',T,' sample=', S, ' estimate=', N],Mess),
 6708	p_message(Mess).
 6709
 6710estimate_number(1,S,Total,L,N):-
 6711	!,
 6712	estimate_number(L,S,N1),
 6713	N is Total + N1.
 6714estimate_number(T,S,Total,L,N):-
 6715	p_message('New Trial'),
 6716	estimate_number(L,S,N1),
 6717	Total1 is Total + N1,
 6718	T1 is T - 1,
 6719	estimate_number(T1,S,Total1,L,N).
 6720
 6721% estimate_number(+L,+S,-N)
 6722%	estimate the number of legal clauses of length L in the search space
 6723%	estimation based on sample size S
 6724estimate_number(1,_,1):- !.
 6725estimate_number(L,S,N):-
 6726	estimate_proportion(S,L,legal,P,_),
 6727	'$aleph_sat'(lastlit,Last),
 6728	total_clauses(L,Last,Total),
 6729	N is float(P*Total).
 6730
 6731% estimate_proportion(+N,+L,+S,-P,-Clauses)
 6732%	estimate prop. of at most N random clauses of length L and status S
 6733%	clauses are generated without replacement
 6734%	S is one of legal or illegal depending on whether C is inside or
 6735%		outside the mode language provided
 6736%	Clauses is the list of at most N def. clauses
 6737%	If S is a variable then clauses can be legal or illegal
 6738%	Thus estimate_proportion(10000,2,S,P,C) returns the
 6739%		proportion and list of 2 literal clauses which are either
 6740%		legal or illegal in a sample of at most 10000
 6741%	Keeps legal clauses obtained in rselect_legal for later use
 6742estimate_proportion(0,_,_,0,[]):- !.
 6743estimate_proportion(N,L,S,P,Clauses):-
 6744	retractall('$aleph_sat'(random,rselect(_))),
 6745	retractall('$aleph_sat'(random,rselect_legal(L,_,_,_,_))),
 6746	get_random_wo_repl(N,L,Clauses),
 6747	length(Clauses,Total),
 6748	count_clause_status(Clauses,S,A,_),
 6749	(Total = 0 -> P = 0; P is A/Total),
 6750	'$aleph_sat'(example,example(E,T)),
 6751	retractall('$aleph_sat'(random,rselect(_))),
 6752	store_legal_clauses(Clauses,L,E,T).
 6753
 6754% get_random_wo_repl(+N,+L,-List)
 6755%	randomly construct at most N definite clauses of length L
 6756%	returns Status/Clause list where Status is one of legal/illegal
 6757get_random_wo_repl(0,_,[]):- !.
 6758get_random_wo_repl(N,L,[S/[C,C1]|Clauses]):-
 6759	randclause_wo_repl(L,C,S,C1), !,
 6760	N1 is N - 1,
 6761	get_random_wo_repl(N1,L,Clauses).
 6762get_random_wo_repl(_,_,[]).
 6763
 6764% print_distribution
 6765print_distribution:-
 6766	write('Clause Length'), tab(8), write('Estimated number of clauses'), nl,
 6767	write('_____________'), tab(8), write('___________________________'), nl,
 6768	findall(L-N,'$aleph_sat'(random,number_of_clauses(L,N)),List),
 6769	sort(List,List1),
 6770	aleph_member(L-N,List1),
 6771	write(L), tab(20), write(N), nl,
 6772	fail.
 6773print_distribution:-
 6774	nl,
 6775	write('Estimated size of hypothesis space = '),
 6776	('$aleph_sat'(random,hypothesis_space(S)) -> true; S = 0),
 6777	write(S), write(' clauses'), nl.
 6778	
 6779% count_clause_status(+List,+Status,-C1,-C2)
 6780%	count number of clauses in List with status Status
 6781%	C1 is the number of such clauses
 6782%	C2 is the number of clauses with some other status
 6783count_clause_status(_,S,_,0):-
 6784	var(S), !.
 6785count_clause_status(Clauses,S,A,B):-
 6786	count_clause_status1(Clauses,S,A,B).
 6787
 6788count_clause_status1([],_,0,0):- !.
 6789count_clause_status1([S1/_|T],S,A,B):-
 6790	count_clause_status1(T,S,A1,B1),
 6791	(S == S1 -> A is A1 + 1, B is B1; A is A1, B is B1 + 1).
 6792
 6793% store_legal_clauses(+List,+L,+E,+T)
 6794% store all legal clauses of length L obtained with bottom clause for
 6795% example E of type T
 6796% useful later when a random legal clause of length L is required
 6797store_legal_clauses([],_,_,_).
 6798store_legal_clauses([S/[C,C1]|Clauses],L,E,T):-
 6799	(S == legal ->
 6800		asserta('$aleph_sat'(random,rselect_legal(L,E,T,C,C1)));
 6801		true),
 6802	store_legal_clauses(Clauses,L,E,T).
 6803
 6804% randclause_wo_repl(+L,-C,-S,-Lits)
 6805% as randclause/4 but ensures that clause obtained is without replacement
 6806%	only makes at most 100 attempts to find such a clause
 6807%	also returns lits from bottom clause selected
 6808%	if all attempts fail, then return the most general clause
 6809randclause_wo_repl(L,C,S,C1):-
 6810	randclause_wo_repl(100,L,C,S,C1).
 6811
 6812randclause_wo_repl(N,L,C,S,C1):-
 6813	N > 0,
 6814	randclause(L,C,S,C1),	% if not accounting for variable renamings
 6815	% copy_term(C,C1),	% if accounting for variable renamings	
 6816	% numbervars(C1,0,_),	% if accounting for variable renamings
 6817	\+(prune(C)),
 6818	split_clause(C,Head,Body),
 6819	(setting(language,Lang) ->
 6820		lang_ok(Lang,Head,Body);
 6821		true),
 6822	(setting(newvars,NewVars) ->
 6823		newvars_ok(NewVars,Head,Body);
 6824		true),
 6825	\+('$aleph_sat'(random,rselect(C1))), !,
 6826	asserta('$aleph_sat'(random,rselect(C1))).
 6827randclause_wo_repl(N,L,C,S,C1):-
 6828	N > 0,
 6829	N1 is N - 1,
 6830	randclause_wo_repl(N1,L,C,S,C1), !.
 6831randclause_wo_repl(_,1,C,S,C1):-
 6832	randclause(1,C,S,C1).	% if not accounting for variable renamings
 6833	% copy_term(C,C1),	% if accounting for variable renamings	
 6834	% numbervars(C1,0,_),	% if accounting for variable renamings
 6835
 6836% randclause(+L,-C,-S,-Lits)
 6837%	returns definite clause C of length L with status S comprised of Lits
 6838%	drawn at random from the bottom clause
 6839%	also returns the literals in the bottom clause that were selected
 6840%	body literals of C are randomly selected from the bottom clause
 6841%	S is one of legal or illegal depending on whether C is inside or
 6842%		outside the mode language provided
 6843% needs a bottom clause to be constructed before it is meaningful
 6844% this can be done with the sat predicate for eg: sat(1)
 6845% if set(store_bottom,true) then use stored bottom clause instead
 6846% if S is legal, then checks to see if previously generated legal
 6847% clauses exist for this bottom clause (these would have been generated
 6848% when trying to estimate the number of legal clause at each length)
 6849randclause(1,C,legal,[1]):-
 6850	!,
 6851	bottom_key(_,_,Key,_),
 6852        (Key = false ->
 6853		get_pclause([1],[],C,_,_,_);
 6854		get_pclause([1],Key,[],C,_,_,_)).
 6855randclause(L,C,Status,Lits):-
 6856	Status == legal,
 6857	'$aleph_sat'(example,example(E,T)),
 6858	retract('$aleph_sat'(random,rselect_legal(L,E,T,C,Lits))).
 6859% can do things more efficiently if we want to generate legal clauses only
 6860randclause(L,C,Status,Lits):-
 6861	Status == legal, !,
 6862	bottom_key(_,_,Key,_),
 6863        (Key = false ->
 6864        	'$aleph_sat_litinfo'(1,_,_,_,_,D);
 6865		'$aleph_sat_litinfo'(1,Key,_,_,_,_,D)),
 6866        L1 is L - 1,
 6867        repeat,
 6868        randselect1(L1,Key,D,[1],BodyLits),
 6869        Lits = [1|BodyLits],
 6870	clause_status(Lits,Key,[],legal,legal), !,
 6871        (Key = false ->
 6872        	get_pclause(Lits,[],C,_,_,_);
 6873        	get_pclause(Lits,Key,[],C,_,_,_)).
 6874randclause(L,C,Status,Lits):-
 6875	L1 is L - 1,
 6876	bottom_key(_,_,Key,_),
 6877	(Key = false ->
 6878		'$aleph_sat'(lastlit,Last);
 6879		'$aleph_sat'(lastlit,Key,Last)),
 6880	repeat,
 6881	randselect(L1,Last,Key,[],BodyLits),
 6882	aleph_append(BodyLits,[1],Lits),
 6883	clause_status(Lits,Key,[],legal,Status1),
 6884	Status1 = Status, !,
 6885        (Key = false ->
 6886        	get_pclause(Lits,[],C,_,_,_);
 6887        	get_pclause(Lits,Key,[],C,_,_,_)).
 6888
 6889% clause_status(+Lits,+LitsSoFar,+StatusSoFar,-Status)
 6890% compute status of a clause
 6891%	Lits is the lits left to add to the clause
 6892%	LitsSoFar is the lits in the clause so far
 6893%	StatusSoFar is the Status of the clause so far
 6894%		if a literal to be added contains unbound input vars then
 6895%		status is illegal
 6896clause_status(Lits,LitsSoFar,Status1,Status2):-
 6897	bottom_key(_,_,Key,_),
 6898	clause_status(Lits,Key,LitsSoFar,Status1,Status2).
 6899
 6900clause_status([],_,_,S,S):- !.
 6901clause_status([Lit|Lits],Key,LitsSoFar,S,S1):-
 6902	get_ovars(LitsSoFar,Key,[],OVars),
 6903	get_ivars([Lit],Key,[],IVars),
 6904	aleph_subset1(IVars,OVars), !,
 6905	aleph_append([Lit],LitsSoFar,Lits1),
 6906	clause_status(Lits,Key,Lits1,S,S1).
 6907clause_status(_,_,_,_,illegal).
 6908
 6909	
 6910% randselect(+L,+Last,+Key,+LitsSoFar,-Lits)
 6911% randomly select L distinct literals to give Lits
 6912% Last is the last literal number in the bottom clause
 6913% LitsSoFar is the literals selected so far
 6914randselect(0,_,_,_,[]):- !.
 6915randselect(_,Last,_,LitsSoFar,[]):-
 6916        length(LitsSoFar,L1),
 6917        L1 is Last - 1, !.
 6918randselect(L,Last,Key,LitsSoFar,[LitNum|Lits]):-
 6919	get_rand_lit(Last,Key,LitsSoFar,LitNum),
 6920	L1 is L - 1,
 6921	randselect(L1,Last,Key,[LitNum|LitsSoFar],Lits).
 6922
 6923% randselect1(+L,+Key,+Avail,+LitsSoFar,-Lits)
 6924% randomly select L distinct literals from Avail to give Lits
 6925% LitsSoFar is the literals selected so far
 6926randselect1(0,_,_,_,[]):- !.
 6927randselect1(_,_,[],_,[]):- !.
 6928randselect1(L,Key,Avail,LitsSoFar,[LitNum|Lits]):-
 6929	random_select(LitNum,Avail,Left),
 6930	(Key = false ->
 6931        	'$aleph_sat_litinfo'(LitNum,_,_,_,_,D);
 6932        	'$aleph_sat_litinfo'(LitNum,Key,_,_,_,_,D)), 
 6933        update_list(D,Left,Left1),
 6934        aleph_delete_list([LitNum|LitsSoFar],Left1,Avail1),
 6935        L1 is L - 1,
 6936        randselect1(L1,Key,Avail1,[LitNum|LitsSoFar],Lits).
 6937 
 6938% get_rand_lit(+Last,+Key,+LitsSoFar,-LitNum)
 6939% randomly select a literal number from 2 - Last
 6940% and not in list LitsSoFar
 6941%	2 because 1 is reserved for head literal
 6942get_rand_lit(Last,Key,LitsSoFar,LitNum):-
 6943	repeat,
 6944	get_rand_lit(Last,Key,LitNum),
 6945	\+(aleph_member(LitNum,LitsSoFar)),
 6946	!.
 6947
 6948% have to use repeat/0 in case literal number from random no generator
 6949%	no longer exists in lits database
 6950get_rand_lit(Last,Key,LitNum):-
 6951	repeat,
 6952	get_random(Last,LitNum),
 6953	LitNum > 1,
 6954	(Key = false ->
 6955        	'$aleph_sat_litinfo'(LitNum,_,_,_,_,_);
 6956        	'$aleph_sat_litinfo'(LitNum,Key,_,_,_,_,_)), !.
 6957
 6958% total_clauses(+L,+N1,-N2)
 6959%	total number of clauses of length L is N2
 6960%	constructed from bottom clause of length N1
 6961total_clauses(1,_,1.0):- !.
 6962total_clauses(L,Bot,N):-
 6963	L1 is L - 1,
 6964	Bot1 is Bot - 1,
 6965	total_clauses(L1,Bot1,N1),
 6966	N is N1*Bot1.
 6967
 6968% num_to_length(+N,+CL,-L)
 6969%	find length of clause numbered N
 6970%	clause length should be =< CL
 6971
 6972num_to_length(N,_,1):- N =< 1.0, !.
 6973num_to_length(N,CL,L):-
 6974	num_to_length1(2,CL,N,1.0,L).
 6975
 6976num_to_length1(L,CL,_,_,CL):-
 6977	L >= CL, !.
 6978num_to_length1(L,CL,N,TotalSoFar,Length):-
 6979	'$aleph_sat'(random,number_of_clauses(L,T)),
 6980	NClauses is TotalSoFar + T,
 6981	(N =< NClauses ->  
 6982		(T < 1.0 -> Length is L - 1; Length = L) ;
 6983		L1 is L + 1,
 6984		num_to_length1(L1,CL,N,NClauses,Length)).
 6985
 6986% refinement operator for randomised local search
 6987%	Type is one of clauses or theories
 6988rls_refine(clauses,_-[_,_,_,false],Clause):-
 6989	!,
 6990	sample_clauses(1,[Clause]),
 6991	\+(old_move(clauses,Clause)).
 6992rls_refine(clauses,Clause1,Clause2):-
 6993	setting(moves,Max),
 6994	MaxMoves is Max,
 6995	once(retract('$aleph_search'(rls_move,M))),
 6996	M =< MaxMoves,
 6997	p1_message('move'), p_message(M),
 6998	M1 is M + 1,
 6999	asserta('$aleph_search'(rls_move,M1)),
 7000	clause_move(Move,Clause1,Clause2),
 7001	p_message(Move),
 7002	\+(old_move(clauses,Clause2)).
 7003
 7004rls_refine(theories,[_-[_,_,_,false]],Theory):-
 7005	!,
 7006	once(theory_move(add_clause,[],Theory)),
 7007	\+(old_move(theories,Theory)).
 7008rls_refine(theories,Theory1,Theory2):-
 7009	setting(moves,MaxMoves),
 7010	once(retract('$aleph_search'(rls_move,M))),
 7011	M =< MaxMoves,
 7012	p1_message('move'), p_message(M),
 7013	M1 is M + 1,
 7014	asserta('$aleph_search'(rls_move,M1)),
 7015	theory_move(_,Theory1,Theory2),
 7016	\+(old_move(theories,Theory2)).
 7017
 7018% clause_move(+Type,+C1,-C2)
 7019% local moves from clause C1 to give C2
 7020%	A move is:
 7021%	a) delete a literal from C1 (Type = delete_lit)
 7022%	b) add a legal literal to C1 (Type = add_lit)
 7023clause_move(delete_lit,C1,C2):-
 7024	C1 = L-[E,T,Lits,Clause],
 7025	(Lits = [H|Rest] ->
 7026		aleph_delete(_,Rest,Left),
 7027		Lits1 = [H|Left],
 7028		bottom_key(E,T,Key,_),
 7029		clause_status(Lits1,Key,[],legal,legal),
 7030		L1 is L - 1,
 7031		(Key = false ->
 7032        		get_pclause(Lits1,[],Clause1,_,_,_);
 7033        		get_pclause(Lits1,Key,[],Clause1,_,_,_)),
 7034		\+(prune(Clause1)) ;
 7035		clause_to_list(Clause,[Head|Body]),
 7036		aleph_delete(_,Body,Left),
 7037		aleph_mode_linked([Head|Left]),
 7038		list_to_clause([Head|Left],Clause1),
 7039		\+(prune(Clause1)),
 7040		L1 is L - 1,
 7041		Lits1 = []),
 7042	C2 = L1-[E,T,Lits1,Clause1].
 7043clause_move(add_lit,C1,C2):-
 7044	C1 = L-[E,T,Lits,Clause],
 7045	setting(clauselength,CL),
 7046	L < CL,
 7047	(Lits = [] ->
 7048		auto_refine(Clause,Clause1),
 7049		L1 is L + 1,
 7050		Lits1 = [];
 7051		aleph_delete(Lit,Lits,Left),
 7052		bottom_key(E,T,Key,_),
 7053		(Key = false ->
 7054        		'$aleph_sat_litinfo'(Lit,_,_,_,_,D);
 7055        		'$aleph_sat_litinfo'(Lit,Key,_,_,_,_,D)),
 7056		aleph_member(Lit1,D),
 7057		\+(aleph_member(Lit1,Left)),
 7058		aleph_append([Lit1],Lits,Lits1),
 7059        	clause_status(Lits1,Key,[],legal,legal),
 7060		L1 is L + 1,
 7061		(Key = false ->
 7062        		get_pclause(Lits1,[],Clause1,_,_,_);
 7063        		get_pclause(Lits1,Key,[],Clause1,_,_,_)),
 7064		\+(prune(Clause1))),
 7065	C2 = L1-[E,T,Lits1,Clause1].
 7066
 7067% theory_move(+Type,+T1,-T2)
 7068% local moves from theory T1 to give T2
 7069%	A move is:
 7070%	a) delete a clause from T1 (Type = delete_clause)
 7071%	b) add a legal clause to  T1  (Type = add_clause)
 7072%	c) delete a literal from a clause in T1 (Type = delete_lit)
 7073%	d) add a legal literal to a clause in T1 (Type = add_lit)
 7074theory_move(delete_clause,T1,T2):-
 7075	aleph_delete(_,T1,T2),
 7076	T2 \= [].
 7077theory_move(add_clause,T1,T2):-
 7078	setting(clauses,Max),
 7079	length(T1,L),
 7080	L < Max,
 7081	sample_clauses(1,[Clause]),
 7082	aleph_append([Clause],T1,T2).
 7083theory_move(delete_lit,T1,T2):-
 7084	aleph_delete(Clause,T1,T),
 7085	clause_move(delete_lit,Clause,Clause1),
 7086	aleph_append([Clause1],T,T2).
 7087theory_move(add_lit,T1,T2):-
 7088	aleph_delete(Clause,T1,T),
 7089	clause_move(add_lit,Clause,Clause1),
 7090	aleph_append([Clause1],T,T2).
 7091
 7092old_move(clauses,N-[_,_,L,C]):-
 7093	(setting(cache_clauselength,N1) -> true; N1 = 3),
 7094	N =< N1,
 7095	(L = [] ->
 7096		clause_to_list(C,C1),
 7097		sort(C1,Hash),
 7098		numbervars(Hash,0,_);
 7099		sort(L,Hash)),
 7100	('$aleph_search_seen'(N,Hash) ->
 7101		p_message('old move'),
 7102		true;
 7103		asserta('$aleph_search_seen'(N,Hash)), !,
 7104		fail).
 7105old_move(theories,T):-
 7106	% remove_alpha_variants(T,T1),
 7107	numbervars(T,0,_),
 7108	length(T,N),
 7109	('$aleph_search_seen'(N,_Hash) ->
 7110		p_message('old move'),
 7111		true;
 7112		asserta('$aleph_search_seen'(N,_Hash)), !,
 7113		fail).
 7114		
 7115extract_clauses_with_length([],[]).
 7116extract_clauses_with_length([L-[_,_,_,C]|T],[L-C|T1]):-
 7117	extract_clauses_with_length(T,T1).
 7118
 7119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 7120% U T I L I T I E S
 7121
 7122% concatenate elements of a list into an atom
 7123
 7124concat([Atom],Atom):- !.
 7125concat([H|T],Atom):-
 7126        concat(T,AT),
 7127        name(AT,L2),
 7128        name(H,L1),
 7129        aleph_append(L2,L1,L),
 7130        name(Atom,L).
 7131
 7132
 7133split_clause((Head:-true),Head,true):- !.
 7134split_clause((Head:-Body1),Head,Body2):- !, Body1 = Body2.
 7135split_clause([Head|T],Head,T):- !.
 7136split_clause([Head],Head,[true]):- !.
 7137split_clause(Head,Head,true).
 7138
 7139strip_true((Head:-true),Head):- !.
 7140strip_true(Clause,Clause).
 7141
 7142% pretty print a definite clause
 7143pp_dclause(Clause):-
 7144        ('$aleph_global'(portray_literals,set(portray_literals,true))->
 7145                pp_dclause(Clause,true);
 7146                pp_dclause(Clause,false)).
 7147
 7148% pretty print a set of definite clauses
 7149pp_dclauses(Theory):-
 7150        aleph_member(_-[_,_,_,Clause],Theory),
 7151        pp_dclause(Clause),
 7152        fail.
 7153pp_dclauses(_):- nl.
 7154 
 7155pp_dclause((H:-true),Pretty):-
 7156        !,
 7157        pp_dclause(H,Pretty).
 7158pp_dclause((H:-B),Pretty):-
 7159        !,
 7160        copy_term((H:-B),(Head:-Body)),
 7161        numbervars((Head:-Body),0,_),
 7162        aleph_portray(Head,Pretty),
 7163        (Pretty = true ->
 7164                write(' if:');
 7165                write(' :-')),
 7166        nl,
 7167        '$aleph_global'(print,set(print,N)),
 7168        print_lits(Body,Pretty,1,N).
 7169
 7170pp_dclause((Lit),Pretty):-
 7171        copy_term(Lit,Lit1),
 7172        numbervars(Lit1,0,_),
 7173        aleph_portray(Lit1,Pretty),
 7174        write('.'), nl.
 7175 
 7176% pretty print a definite clause list: head of list is + literal
 7177pp_dlist([]):- !.
 7178pp_dlist(Clause):-
 7179        ('$aleph_global'(portray_literals,set(portray_literals,true))->
 7180                pp_dlist(Clause,true);
 7181                pp_dlist(Clause,false)).
 7182 
 7183pp_dlist(Clause,Pretty):-
 7184        copy_term(Clause,[Head1|Body1]),
 7185        numbervars([Head1|Body1],0,_),
 7186        aleph_portray(Head1,Pretty),
 7187        (Body1 = [] ->
 7188                write('.'), nl;
 7189                (Pretty = true ->
 7190                        write(' if:');
 7191                        write(' :-')),
 7192        nl,
 7193        '$aleph_global'(print,set(print,N)),
 7194        print_litlist(Body1,Pretty,1,N)).
 7195 
 7196print_litlist([],_,_,_).
 7197print_litlist([Lit],Pretty,LitNum,_):-
 7198        !,
 7199        print_lit(Lit,Pretty,LitNum,LitNum,'.',_).
 7200print_litlist([Lit|Lits],Pretty,LitNum,LastLit):-
 7201        print_lit(Lit,Pretty,LitNum,LastLit,', ',NextLit),
 7202        print_litlist(Lits,Pretty,NextLit,LastLit).
 7203 
 7204print_lits((Lit,Lits),Pretty,LitNum,LastLit):-
 7205        !,
 7206        (Pretty = true ->
 7207                Sep = ' and ';
 7208                Sep = ', '),
 7209        print_lit(Lit,Pretty,LitNum,LastLit,Sep,NextLit),
 7210        print_lits(Lits,Pretty,NextLit,LastLit).
 7211print_lits((Lit),Pretty,LitNum,_):-
 7212        print_lit(Lit,Pretty,LitNum,LitNum,'.',_).
 7213
 7214print_lit(Lit,Pretty,LitNum,LastLit,Sep,NextLit):-
 7215        (LitNum = 1 -> tab(3);true),
 7216        aleph_portray(Lit,Pretty), write(Sep),
 7217        (LitNum=LastLit-> nl,NextLit=1; NextLit is LitNum + 1).
 7218 
 7219p1_message(Mess):-
 7220	write('['), write(Mess), write('] ').
 7221
 7222p_message(Mess):-
 7223	write('['), write(Mess), write(']'), nl.
 7224
 7225err_message(Mess):-
 7226	p1_message('error'), p_message(Mess).
 7227
 7228aleph_delete_all(_,[],[]).
 7229aleph_delete_all(X,[Y|T],T1):-
 7230        X == Y, !,
 7231        aleph_delete_all(X,T,T1).
 7232aleph_delete_all(X,[Y|T],[Y|T1]):-
 7233        aleph_delete_all(X,T,T1).
 7234
 7235aleph_delete_list([],L,L).
 7236aleph_delete_list([H1|T1],L1,L):-
 7237	aleph_delete(H1,L1,L2), !,
 7238	aleph_delete_list(T1,L2,L).
 7239aleph_delete_list([_|T1],L1,L):-
 7240	aleph_delete_list(T1,L1,L).
 7241
 7242aleph_delete(H,[H|T],T).
 7243aleph_delete(H,[H1|T],[H1|T1]):-
 7244	aleph_delete(H,T,T1).
 7245
 7246aleph_delete1(H,[H|T],T):- !.
 7247aleph_delete1(H,[H1|T],[H1|T1]):-
 7248	aleph_delete1(H,T,T1).
 7249
 7250aleph_delete0(_,[],[]).
 7251aleph_delete0(H,[H|T],T):- !.
 7252aleph_delete0(H,[H1|T],[H1|T1]):-
 7253	aleph_delete0(H,T,T1).
 7254
 7255aleph_append(A,[],A):-!.
 7256aleph_append(A,[H|T],[H|T1]):-
 7257	aleph_append(A,T,T1).
 7258
 7259% aleph_remove_nth(+N,+List1,-Elem,-List2)
 7260%	remove the nth elem from a List
 7261aleph_remove_nth(1,[H|T],H,T):- !.
 7262aleph_remove_nth(N,[H|T],X,[H|T1]):-
 7263        N1 is N - 1,
 7264        aleph_remove_nth(N1,T,X,T1).
 7265
 7266% aleph_remove_n(+N,+List1,-List2,-List3)
 7267%	remove the n elems from List1 into List2. List3 is the rest of List1
 7268aleph_remove_n(0,L,[],L):- !.
 7269aleph_remove_n(_,[],[],[]):- !.
 7270aleph_remove_n(N,[H|T],[H|T1],L):-
 7271	N1 is N - 1,
 7272	aleph_remove_n(N1,T,T1,L).
 7273
 7274% aleph_rpermute(+List1,-List2)
 7275%	randomly permute the elements of List1 into List2
 7276aleph_rpermute(List1,List2):-
 7277	length(List1,N1),
 7278	aleph_rpermute(List1,N1,List2).
 7279
 7280aleph_rpermute([],0,[]):- !.
 7281aleph_rpermute(L1,N1,[X|Rest]):-
 7282	get_random(N1,R),
 7283	aleph_remove_nth(R,L1,X,L2),
 7284	N2 is N1 - 1,
 7285	aleph_rpermute(L2,N2,Rest).
 7286
 7287% aleph_rsample(+N,+List1,-List2)
 7288%	randomly sample N elements from List1 into List2
 7289aleph_rsample(N,List1,List2):-
 7290	length(List1,N1),
 7291	aleph_rsample(N,N1,List1,List2).
 7292
 7293aleph_rsample(N,N1,L,L):- N >= N1, !.
 7294aleph_rsample(SampleSize,Total,[X|L1],[X|L2]):-
 7295	get_random(Total,R),
 7296	R =< SampleSize, !,
 7297	SampleSize0 is SampleSize - 1,
 7298	Total0 is Total - 1,
 7299	aleph_rsample(SampleSize0,Total0,L1,L2).
 7300aleph_rsample(SampleSize,Total,[_|L1],L2):-
 7301	Total0 is Total - 1,
 7302	aleph_rsample(SampleSize,Total0,L1,L2).
 7303
 7304% get_first_n(+N,+List1,-List2)
 7305%	get the first n elements in List1
 7306get_first_n(0,_,[]):- !.
 7307get_first_n(_,[],[]):- !.
 7308get_first_n(N,[H|T],[H|T1]):-
 7309	N1 is N - 1,
 7310	get_first_n(N1,T,T1).
 7311
 7312% erase_refs(+List)
 7313%	erase database references: only works for Yap
 7314erase_refs([]).
 7315erase_refs([DbRef|DbRefs]):-
 7316	erase(DbRef),
 7317	erase_refs(DbRefs).
 7318
 7319
 7320% max_in_list(+List,-Max)
 7321%	return largest element in a list
 7322max_in_list([X],X):- !.
 7323max_in_list([X|T],Z):-
 7324	max_in_list(T,Y),
 7325	(X @> Y -> Z = X; Z = Y). 
 7326
 7327% min_in_list(+List,-Max)
 7328%	return largest element in a list
 7329min_in_list([X],X):- !.
 7330min_in_list([X|T],Z):-
 7331	min_in_list(T,Y),
 7332	(X @> Y -> Z = Y; Z = X). 
 7333
 7334% remove_alpha_variants(+List1,-List2):-
 7335%	remove alphabetic variants from List1 to give List2
 7336remove_alpha_variants([],[]).
 7337remove_alpha_variants([X|Y],L):-
 7338	aleph_member(X1,Y),
 7339	alphabetic_variant(X,X1), !,
 7340	remove_alpha_variants(Y,L).
 7341remove_alpha_variants([X|Y],[X|L]):-
 7342	remove_alpha_variants(Y,L).
 7343 
 7344% alphabetic_variant(+Term1,+Term2)
 7345%	true if Term1 is the alphabetic variant of Term2
 7346alphabetic_variant(Term1,Term2):-
 7347	copy_term(Term1/Term2,T1/T2),
 7348	numbervars(T1,0,_),
 7349	numbervars(T2,0,_),
 7350	T1 = T2.
 7351
 7352% tparg(+TermPlace,+Term1,?Term2)
 7353% return Term2 at position specified by TermPlace in Term1
 7354tparg([Place],Term,Arg):-
 7355        !,
 7356        arg(Place,Term,Arg).
 7357tparg([Place|Places],Term,Arg):-
 7358        arg(Place,Term,Term1),
 7359        tparg(Places,Term1,Arg).
 7360
 7361
 7362aleph_member1(H,[H|_]):- !.
 7363aleph_member1(H,[_|T]):-
 7364	aleph_member1(H,T).
 7365
 7366aleph_member2(X,[Y|_]):- X == Y, !.
 7367aleph_member2(X,[_|T]):-
 7368	aleph_member2(X,T).
 7369
 7370aleph_member3(A,A-B):- A =< B.
 7371aleph_member3(X,A-B):-
 7372	A < B,
 7373	A1 is A + 1,
 7374	aleph_member3(X,A1-B).
 7375
 7376aleph_member(X,[X|_]).
 7377aleph_member(X,[_|T]):-
 7378	aleph_member(X,T).
 7379
 7380aleph_reverse(L1, L2) :- revzap(L1, [], L2).
 7381
 7382revzap([X|L], L2, L3) :- revzap(L, [X|L2], L3).
 7383revzap([], L, L).
 7384
 7385goals_to_clause((Head,Body),(Head:-Body)):- !.
 7386goals_to_clause(Head,Head).
 7387
 7388clause_to_list((Head:-true),[Head]):- !.
 7389clause_to_list((Head:-Body),[Head|L]):-
 7390        !,
 7391        goals_to_list(Body,L).
 7392clause_to_list(Head,[Head]).
 7393
 7394extend_clause(false,Lit,(Lit)):- !.
 7395extend_clause((Head:-Body),Lit,(Head:-Body1)):-
 7396        !,
 7397        app_lit(Lit,Body,Body1).
 7398extend_clause(Head,Lit,(Head:-Lit)).
 7399 
 7400app_lit(L,(L1,L2),(L1,L3)):-
 7401        !,
 7402        app_lit(L,L2,L3).
 7403app_lit(L,L1,(L1,L)).
 7404
 7405prefix_lits(L,true,L):- !.
 7406prefix_lits(L,L1,((L),L1)).
 7407
 7408get_goaldiffs((G1,G2),(G1,G3),Diffs):-
 7409	!,
 7410	get_goaldiffs(G2,G3,Diffs).
 7411get_goaldiffs(true,G,G):- !.
 7412get_goaldiffs(G1,(G1,G2),G2).
 7413
 7414nlits((_:-B),N):-
 7415	!,
 7416	nlits(B,N1),
 7417	N is N1 + 1.
 7418nlits((_,Lits),N):-
 7419	!,
 7420	nlits(Lits,N1),
 7421	N is N1 + 1.
 7422nlits(_,1).
 7423
 7424
 7425list_to_clause([Goal],(Goal:-true)):- !.
 7426list_to_clause([Head|Goals],(Head:-Body)):-
 7427	list_to_goals(Goals,Body).
 7428
 7429list_to_goals([Goal],Goal):- !.
 7430list_to_goals([Goal|Goals],(Goal,Goals1)):-
 7431	list_to_goals(Goals,Goals1).
 7432
 7433goals_to_list((true,Goals),T):-
 7434	!,
 7435	goals_to_list(Goals,T).
 7436goals_to_list((Goal,Goals),[Goal|T]):-
 7437	!,
 7438	goals_to_list(Goals,T).
 7439goals_to_list(true,[]):- !.
 7440goals_to_list(Goal,[Goal]).
 7441
 7442% get_litnums(+First,+Last,-LitNums)
 7443%	get list of Literal numbers in the bottom clause
 7444get_litnums(LitNum,Last,[]):-
 7445        LitNum > Last, !.
 7446get_litnums(LitNum,Last,[LitNum|LitNums]):-
 7447        '$aleph_sat_litinfo'(LitNum,_,_,_,_,_), !,
 7448        NextLit is LitNum + 1,
 7449        get_litnums(NextLit,Last,LitNums).
 7450get_litnums(LitNum,Last,LitNums):-
 7451        NextLit is LitNum + 1,
 7452        get_litnums(NextLit,Last,LitNums).
 7453
 7454get_clause(LitNum,Last,_,[]):-
 7455        LitNum > Last, !.
 7456get_clause(LitNum,Last,TVSoFar,[FAtom|FAtoms]):-
 7457        '$aleph_sat_litinfo'(LitNum,_,Atom,_,_,_), !,
 7458        get_flatatom(Atom,TVSoFar,FAtom,TV1),
 7459        NextLit is LitNum + 1,
 7460        get_clause(NextLit,Last,TV1,FAtoms).
 7461get_clause(LitNum,Last,TVSoFar,FAtoms):-
 7462        NextLit is LitNum + 1,
 7463        get_clause(NextLit,Last,TVSoFar,FAtoms).
 7464
 7465get_flatatom(not(Atom),TVSoFar,not(FAtom),TV1):-
 7466        !,
 7467        get_flatatom(Atom,TVSoFar,FAtom,TV1).
 7468get_flatatom(Atom,TVSoFar,FAtom,TV1):-
 7469        functor(Atom,Name,Arity),
 7470        functor(FAtom,Name,Arity),
 7471        flatten_args(Arity,Atom,FAtom,TVSoFar,TV1).
 7472
 7473get_pclause([LitNum],TVSoFar,Clause,TV,Length,LastDepth):-
 7474        !,
 7475        get_pclause1([LitNum],TVSoFar,TV,Clause,Length,LastDepth).
 7476get_pclause([LitNum|LitNums],TVSoFar,Clause,TV,Length,LastDepth):-
 7477        get_pclause1([LitNum],TVSoFar,TV1,Head,Length1,_),
 7478        get_pclause1(LitNums,TV1,TV,Body,Length2,LastDepth),
 7479	Clause = (Head:-Body),
 7480        Length is Length1 + Length2.
 7481
 7482get_pclause1([LitNum],TVSoFar,TV1,Lit,Length,LastDepth):-
 7483        !,
 7484        '$aleph_sat_litinfo'(LitNum,LastDepth,Atom,_,_,_),
 7485        get_flatatom(Atom,TVSoFar,Lit,TV1),
 7486        functor(Lit,Name,_),
 7487        (Name = '='-> Length = 0; Length = 1).
 7488get_pclause1([LitNum|LitNums],TVSoFar,TV2,(Lit,Lits1),Length,LastDepth):-
 7489        '$aleph_sat_litinfo'(LitNum,_,Atom,_,_,_),
 7490        get_flatatom(Atom,TVSoFar,Lit,TV1),
 7491        get_pclause1(LitNums,TV1,TV2,Lits1,Length1,LastDepth),
 7492        functor(Lit,Name,_),
 7493        (Name = '='-> Length = Length1; Length is Length1 + 1).
 7494
 7495get_pclause([LitNum],Key,TVSoFar,Clause,TV,Length,LastDepth):-
 7496        !,
 7497        get_pclause1([LitNum],Key,TVSoFar,TV,Clause,Length,LastDepth).
 7498get_pclause([LitNum|LitNums],Key,TVSoFar,Clause,TV,Length,LastDepth):-
 7499        get_pclause1([LitNum],Key,TVSoFar,TV1,Head,Length1,_),
 7500        get_pclause1(LitNums,Key,TV1,TV,Body,Length2,LastDepth),
 7501	Clause = (Head:-Body),
 7502        Length is Length1 + Length2.
 7503
 7504get_pclause1([LitNum],Key,TVSoFar,TV1,Lit,Length,LastDepth):-
 7505        !,
 7506        '$aleph_sat_litinfo'(LitNum,Key,LastDepth,Atom,_,_,_),
 7507        get_flatatom(Atom,TVSoFar,Lit,TV1),
 7508        functor(Lit,Name,_),
 7509        (Name = '='-> Length = 0; Length = 1).
 7510get_pclause1([LitNum|LitNums],Key,TVSoFar,TV2,(Lit,Lits1),Length,LastDepth):-
 7511        '$aleph_sat_litinfo'(LitNum,Key,_,Atom,_,_,_),
 7512        get_flatatom(Atom,TVSoFar,Lit,TV1),
 7513        get_pclause1(LitNums,Key,TV1,TV2,Lits1,Length1,LastDepth),
 7514        functor(Lit,Name,_),
 7515        (Name = '='-> Length = Length1; Length is Length1 + 1).
 7516
 7517
 7518flatten_args(0,_,_,TV,TV):- !.
 7519flatten_args(Arg,Atom,FAtom,TV,TV1):-
 7520        arg(Arg,Atom,Term),
 7521        Arg1 is Arg - 1,
 7522        (Term = aleph_const(Const) ->
 7523                arg(Arg,FAtom,Const),
 7524                flatten_args(Arg1,Atom,FAtom,TV,TV1);
 7525                (integer(Term) ->
 7526                        update(TV,Term/Var,TV0),
 7527                        arg(Arg,FAtom,Var),
 7528                        flatten_args(Arg1,Atom,FAtom,TV0,TV1);
 7529                        (functor(Term,Name,Arity),
 7530                         functor(FTerm,Name,Arity),
 7531                         arg(Arg,FAtom,FTerm),
 7532                         flatten_args(Arity,Term,FTerm,TV,TV0),
 7533                         flatten_args(Arg1,Atom,FAtom,TV0,TV1)
 7534                        )
 7535                )
 7536        ).
 7537
 7538
 7539% returns intersection of S1, S2 and S1-Intersection
 7540intersect1(Elems,[],[],Elems):- !.
 7541intersect1([],_,[],[]):- !.
 7542intersect1([Elem|Elems],S2,[Elem|Intersect],ElemsLeft):-
 7543	aleph_member1(Elem,S2), !,
 7544	intersect1(Elems,S2,Intersect,ElemsLeft).
 7545intersect1([Elem|Elems],S2,Intersect,[Elem|ElemsLeft]):-
 7546	intersect1(Elems,S2,Intersect,ElemsLeft).
 7547
 7548aleph_subset1([],_).
 7549aleph_subset1([Elem|Elems],S):-
 7550	aleph_member1(Elem,S), !,
 7551	aleph_subset1(Elems,S).
 7552
 7553aleph_subset2([X|Rest],[X|S]):-
 7554	aleph_subset2(Rest,S).
 7555aleph_subset2(S,[_|S1]):-
 7556	aleph_subset2(S,S1).
 7557aleph_subset2([],[]).
 7558
 7559% two sets are equal
 7560
 7561equal_set([],[]).
 7562equal_set([H|T],S):-
 7563	aleph_delete1(H,S,S1),
 7564	equal_set(T,S1), !.
 7565
 7566uniq_insert(_,X,[],[X]).
 7567uniq_insert(descending,H,[H1|T],[H,H1|T]):-
 7568	H @> H1, !.
 7569uniq_insert(ascending,H,[H1|T],[H,H1|T]):-
 7570	H @< H1, !.
 7571uniq_insert(_,H,[H|T],[H|T]):- !.
 7572uniq_insert(Order,H,[H1|T],[H1|T1]):-
 7573	!,
 7574	uniq_insert(Order,H,T,T1).
 7575
 7576quicksort(_,[],[]).
 7577quicksort(Order,[X|Tail],Sorted):-
 7578	partition(X,Tail,Small,Big),
 7579	quicksort(Order,Small,SSmall),
 7580	quicksort(Order,Big,SBig),
 7581        (Order=ascending-> aleph_append([X|SBig],SSmall,Sorted);
 7582                aleph_append([X|SSmall],SBig,Sorted)).
 7583	
 7584partition(_,[],[],[]).
 7585partition(X,[Y|Tail],[Y|Small],Big):-
 7586	X @> Y, !,
 7587	partition(X,Tail,Small,Big).
 7588partition(X,[Y|Tail],Small,[Y|Big]):-
 7589	partition(X,Tail,Small,Big).
 7590
 7591update_list([],L,L).
 7592update_list([H|T],L,Updated):-
 7593	update(L,H,L1), !,
 7594	update_list(T,L1,Updated).
 7595
 7596update([],H,[H]).
 7597update([H|T],H,[H|T]):- !.
 7598update([H1|T],H,[H1|T1]):-
 7599	update(T,H,T1).
 7600
 7601% checks if 2 sets intersect
 7602intersects(S1,S2):-
 7603	aleph_member(Elem,S1), aleph_member1(Elem,S2), !.
 7604
 7605% checks if bitsets represented as lists of intervals intersect
 7606intervals_intersects([L1-L2|_],I):-
 7607	intervals_intersects1(L1-L2,I), !.
 7608intervals_intersects([_|I1],I):-
 7609	intervals_intersects(I1,I).
 7610
 7611intervals_intersects1(L1-_,[M1-M2|_]):-
 7612	L1 >= M1, L1 =< M2, !.
 7613intervals_intersects1(L1-L2,[M1-_|_]):-
 7614	M1 >= L1, M1 =< L2, !.
 7615intervals_intersects1(L1-L2,[_|T]):-
 7616	intervals_intersects1(L1-L2,T).
 7617
 7618% checks if bitsets represented as lists of intervals intersect
 7619% returns first intersection
 7620intervals_intersects([L1-L2|_],I,I1):-
 7621	intervals_intersects1(L1-L2,I,I1), !.
 7622intervals_intersects([_|ILeft],I,I1):-
 7623	intervals_intersects(ILeft,I,I1).
 7624
 7625intervals_intersects1(I1,[I2|_],I):-
 7626	interval_intersection(I1,I2,I), !.
 7627intervals_intersects1(I1,[_|T],I):-
 7628	intervals_intersects1(I1,T,I).
 7629
 7630interval_intersection(L1-L2,M1-M2,L1-L2):-
 7631	L1 >= M1, L2 =< M2, !.
 7632interval_intersection(L1-L2,M1-M2,M1-M2):-
 7633	M1 >= L1, M2 =< L2, !.
 7634interval_intersection(L1-L2,M1-M2,L1-M2):-
 7635	L1 >= M1, M2 >= L1, M2 =< L2, !.
 7636interval_intersection(L1-L2,M1-M2,M1-L2):-
 7637	M1 >= L1, M1 =< L2, L2 =< M2, !.
 7638
 7639%most of the time no intersection, so optimise on that
 7640% optimisation by James Cussens
 7641intervals_intersection([],_,[]).
 7642intervals_intersection([A-B|T1],[C-D|T2],X) :-
 7643        !,
 7644        (A > D ->
 7645            intervals_intersection([A-B|T1],T2,X);
 7646            (C > B ->
 7647                intervals_intersection(T1,[C-D|T2],X);
 7648                (B > D ->
 7649                    (C > A ->
 7650                        X=[C-D|Y];
 7651                        X=[A-D|Y]
 7652                    ),
 7653                    intervals_intersection([A-B|T1],T2,Y);
 7654                    (C > A ->
 7655                        X=[C-B|Y];
 7656                        X=[A-B|Y]
 7657                    ),
 7658                    intervals_intersection(T1,[C-D|T2],Y)
 7659                )
 7660            )
 7661        ).
 7662intervals_intersection(_,[],[]).
 7663
 7664
 7665% finds length of intervals in a list
 7666interval_count([],0).
 7667interval_count([L1-L2|T],N):-
 7668	N1 is L2 - L1 + 1,
 7669	interval_count(T,N2),
 7670	N is N1 + N2.
 7671interval_count(I/_,N):-
 7672	interval_count(I,N).
 7673
 7674% interval_select(+N,+List1,-Elem)
 7675%       select the Nth elem from an interval list
 7676interval_select(N,[A-B|_],X):-
 7677        N =< B - A + 1, !,
 7678        X is A + N - 1.
 7679interval_select(N,[A-B|T],X):-
 7680        N1 is N - (B - A + 1),
 7681        interval_select(N1,T,X).
 7682
 7683% interval_sample(+N,List1,-List2)
 7684%	get a random sample of N elements from List1
 7685interval_sample(N,List1,List2):-
 7686	intervals_to_list(List1,L1),
 7687	aleph_rsample(N,L1,L2),
 7688	list_to_intervals(L2,List2).
 7689
 7690% convert list to intervals
 7691list_to_intervals(List,Intervals):-
 7692	sort(List,List1),
 7693        list_to_intervals1(List1,Intervals).
 7694
 7695list_to_intervals1([],[]).
 7696list_to_intervals1([Start|T],[Start-Finish|I1]):-
 7697        list_to_interval(Start,T,Finish,T1),
 7698        list_to_intervals1(T1,I1).
 7699
 7700list_to_interval(Finish,[],Finish,[]).
 7701list_to_interval(Finish,[Next|T],Finish,[Next|T]):-
 7702        Next - Finish > 1,
 7703        !.
 7704list_to_interval(_,[Start|T],Finish,Rest):-
 7705        list_to_interval(Start,T,Finish,Rest).
 7706
 7707% converts an interval-list into a list of (sorted) numbers
 7708intervals_to_list(L,L1):-
 7709	intervals_to_list(L,[],L0),
 7710	sort(L0,L1), !.
 7711
 7712intervals_to_list([],L,L).
 7713intervals_to_list([Interval|Intervals],L1,L2):-
 7714	interval_to_list(Interval,L1,L),
 7715	intervals_to_list(Intervals,L,L2).
 7716
 7717% converts an interval into a list
 7718interval_to_list(Start-Finish,[]):-
 7719	Start > Finish, !.
 7720interval_to_list(Start-Finish,[Start|T]):-
 7721	Start1 is Start+1,
 7722	interval_to_list(Start1-Finish,T).
 7723
 7724% converts an interval into a list
 7725%	with an accumulator list. Result will be in reverse order
 7726interval_to_list(Start-Finish,L,L):-
 7727	Start > Finish, !.
 7728interval_to_list(Start-Finish,L,L1):-
 7729	Start1 is Start+1,
 7730	interval_to_list(Start1-Finish,[Start|L],L1).
 7731
 7732% interval_subsumes(+I1,+I2)
 7733%	checks to see if interval I1 subsumes I2
 7734interval_subsumes(Start1-Finish1,Start2-Finish2):-
 7735	Start1 =< Start2,
 7736	Finish1 >= Finish2.
 7737
 7738interval_subtract(Start1-Finish1,Start1-Finish1,[]):- !.
 7739interval_subtract(Start1-Finish1,Start1-Finish2,[S2-Finish1]):-
 7740	!,
 7741	S2 is Finish2 + 1.
 7742interval_subtract(Start1-Finish1,Start2-Finish1,[Start1-S1]):-
 7743	!,
 7744	S1 is Start2 - 1.
 7745interval_subtract(Start1-Finish1,Start2-Finish2,[Start1-S1,S2-Finish1]):-
 7746	S1 is Start2 - 1,
 7747	S2 is Finish2 + 1,
 7748	S1 >= Start1, Finish1 >= S2, !.
 7749
 7750
 7751% code for set manipulation utilities 
 7752% taken from the Yap library
 7753% aleph_ord_subtract(+Set1,+Set2,?Difference)
 7754% is true when Difference contains all and only the elements of Set1
 7755% which are not also in Set2.
 7756aleph_ord_subtract(Set1,[],Set1) :- !.
 7757aleph_ord_subtract([],_,[]) :- !.
 7758aleph_ord_subtract([Head1|Tail1],[Head2|Tail2],Difference) :-
 7759        compare(Order,Head1,Head2),
 7760        aleph_ord_subtract(Order,Head1,Tail1,Head2,Tail2,Difference).
 7761
 7762aleph_ord_subtract(=,_,    Tail1,_,    Tail2,Difference) :-
 7763	aleph_ord_subtract(Tail1,Tail2,Difference).
 7764aleph_ord_subtract(<,Head1,Tail1,Head2,Tail2,[Head1|Difference]) :-
 7765        aleph_ord_subtract(Tail1,[Head2|Tail2],Difference).
 7766aleph_ord_subtract(>,Head1,Tail1,_,    Tail2,Difference) :-
 7767        aleph_ord_subtract([Head1|Tail1],Tail2,Difference). 
 7768
 7769% aleph_ord_disjoint(+Set1,+Set2)
 7770% is true when the two ordered sets have no element in common.  If the
 7771% arguments are not ordered,I have no idea what happens.
 7772aleph_ord_disjoint([],_) :- !.
 7773aleph_ord_disjoint(_,[]) :- !.
 7774aleph_ord_disjoint([Head1|Tail1],[Head2|Tail2]) :-
 7775        compare(Order,Head1,Head2),
 7776        aleph_ord_disjoint(Order,Head1,Tail1,Head2,Tail2).
 7777
 7778aleph_ord_disjoint(<,_,Tail1,Head2,Tail2) :-
 7779        aleph_ord_disjoint(Tail1,[Head2|Tail2]).
 7780aleph_ord_disjoint(>,Head1,Tail1,_,Tail2) :-
 7781        aleph_ord_disjoint([Head1|Tail1],Tail2).
 7782
 7783
 7784% aleph_ord_union(+Set1,+Set2,?Union)
 7785% is true when Union is the union of Set1 and Set2.  Note that when
 7786% something occurs in both sets,we want to retain only one copy.
 7787aleph_ord_union(Set1,[],Set1) :- !.
 7788aleph_ord_union([],Set2,Set2) :- !.
 7789aleph_ord_union([Head1|Tail1],[Head2|Tail2],Union) :-
 7790        compare(Order,Head1,Head2),
 7791        aleph_ord_union(Order,Head1,Tail1,Head2,Tail2,Union).
 7792
 7793aleph_ord_union(=,Head, Tail1,_,    Tail2,[Head|Union]) :-
 7794        aleph_ord_union(Tail1,Tail2,Union).
 7795aleph_ord_union(<,Head1,Tail1,Head2,Tail2,[Head1|Union]) :-
 7796        aleph_ord_union(Tail1,[Head2|Tail2],Union).
 7797aleph_ord_union(>,Head1,Tail1,Head2,Tail2,[Head2|Union]) :-
 7798        aleph_ord_union([Head1|Tail1],Tail2,Union).
 7799
 7800% aleph_ord_union(+Set1,+Set2,?Union,?Difference)
 7801% is true when Union is the union of Set1 and Set2 and Difference is the
 7802% difference between Set2 and Set1.
 7803aleph_ord_union(Set1,[],Set1,[]) :- !.
 7804aleph_ord_union([],Set2,Set2,Set2) :- !.
 7805aleph_ord_union([Head1|Tail1],[Head2|Tail2],Union,Diff) :-
 7806        compare(Order,Head1,Head2),
 7807        aleph_ord_union(Order,Head1,Tail1,Head2,Tail2,Union,Diff).
 7808
 7809aleph_ord_union(=,Head, Tail1,_, Tail2,[Head|Union],Diff) :-
 7810        aleph_ord_union(Tail1,Tail2,Union,Diff).
 7811aleph_ord_union(<,Head1,Tail1,Head2,Tail2,[Head1|Union],Diff) :-
 7812        aleph_ord_union(Tail1,[Head2|Tail2],Union,Diff).
 7813aleph_ord_union(>,Head1,Tail1,Head2,Tail2,[Head2|Union],[Head2|Diff]) :-
 7814        aleph_ord_union([Head1|Tail1],Tail2,Union,Diff).
 7815
 7816aleph_ord_intersection(_,[],[]) :- !.
 7817aleph_ord_intersection([],_,[]) :- !.
 7818aleph_ord_intersection([Head1|Tail1],[Head2|Tail2],Intersection) :-
 7819        compare(Order,Head1,Head2),
 7820        aleph_ord_intersection(Order,Head1,Tail1,Head2,Tail2,Intersection).
 7821
 7822aleph_ord_intersection(=,Head,Tail1,_,Tail2,[Head|Intersection]) :-
 7823        aleph_ord_intersection(Tail1,Tail2,Intersection).
 7824aleph_ord_intersection(<,_,Tail1,Head2,Tail2,Intersection) :-
 7825        aleph_ord_intersection(Tail1,[Head2|Tail2],Intersection).
 7826aleph_ord_intersection(>,Head1,Tail1,_,Tail2,Intersection) :-
 7827        aleph_ord_intersection([Head1|Tail1],Tail2,Intersection).
 7828
 7829aleph_ord_subset([], _) :- !.
 7830aleph_ord_subset([Head1|Tail1], [Head2|Tail2]) :-
 7831        compare(Order, Head1, Head2),
 7832        aleph_ord_subset(Order, Head1, Tail1, Head2, Tail2).
 7833
 7834aleph_ord_subset(=, _, Tail1, _, Tail2) :-
 7835        aleph_ord_subset(Tail1, Tail2).
 7836aleph_ord_subset(>, Head1, Tail1, _, Tail2) :-
 7837        aleph_ord_subset([Head1|Tail1], Tail2).
 7838
 7839vars_in_term([],Vars,Vars1):- sort(Vars,Vars1), !.
 7840vars_in_term([Var|T],VarsSoFar,Vars):-
 7841        var(Var), !,
 7842        vars_in_term(T,[Var|VarsSoFar],Vars).
 7843vars_in_term([Term|T],VarsSoFar,Vars):-
 7844        Term =.. [_|Terms], !,
 7845        vars_in_term(Terms,VarsSoFar,V1),
 7846        vars_in_term(T,V1,Vars).
 7847vars_in_term([_|T],VarsSoFar,Vars):-
 7848        vars_in_term(T,VarsSoFar,Vars).
 7849
 7850occurs_in(Vars,(Lit,_)):-
 7851	occurs_in(Vars,Lit), !.
 7852occurs_in(Vars,(_,Lits)):-
 7853	!,
 7854	occurs_in(Vars,Lits).
 7855occurs_in(Vars,Lit):-
 7856	functor(Lit,_,Arity),
 7857	occurs1(Vars,Lit,1,Arity).
 7858
 7859occurs1(Vars,Lit,Argno,MaxArgs):- 
 7860	Argno =< MaxArgs,
 7861	arg(Argno,Lit,Term),
 7862	vars_in_term([Term],[],Vars1),
 7863	aleph_member(X,Vars), aleph_member(Y,Vars1), 
 7864	X == Y, !.
 7865occurs1(Vars,Lit,Argno,MaxArgs):- 
 7866	Argno < MaxArgs,
 7867	Next is Argno + 1,
 7868	occurs1(Vars,Lit,Next,MaxArgs).
 7869
 7870
 7871declare_dynamic(Name/Arity):-
 7872	dynamic Name/Arity.
 7873
 7874aleph_abolish(Name/Arity):-
 7875	functor(Pred,Name,Arity),
 7876	(predicate_property(Pred,dynamic) ->
 7877		retractall(Pred);
 7878		abolish(Name/Arity)).
 7879
 7880aleph_open(File,read,Stream):-
 7881	!,
 7882	(exists(File) ->
 7883		open(File,read,Stream);
 7884		fail).
 7885aleph_open(File,Mode,Stream):-
 7886	open(File,Mode,Stream).
 7887
 7888clean_up:-
 7889        clean_up_init,
 7890        clean_up_sat,
 7891        clean_up_reduce.
 7892
 7893clean_up_init:-
 7894	aleph_abolish('$aleph_good'/3),
 7895	retractall('$aleph_search'(last_good,_)),
 7896	aleph_abolish('$aleph_feature'/2).
 7897	
 7898
 7899clean_up_sat:-
 7900	aleph_abolish('$aleph_sat'/2),
 7901	aleph_abolish('$aleph_local'/2),
 7902	aleph_abolish('$aleph_sat_atom'/2),
 7903	aleph_abolish('$aleph_sat_ovars'/2),
 7904	aleph_abolish('$aleph_sat_ivars'/2),
 7905	aleph_abolish('$aleph_sat_varscopy'/3),
 7906	aleph_abolish('$aleph_sat_varequiv'/3),
 7907	aleph_abolish('$aleph_sat_terms'/4),
 7908	aleph_abolish('$aleph_sat_vars'/4),
 7909	aleph_abolish('$aleph_sat_litinfo'/6),
 7910	retractall('$aleph_search'(pclause,_)),
 7911	gc.
 7912
 7913clean_up_reduce:-
 7914	aleph_abolish('$aleph_local'/2),
 7915	clean_up_search,
 7916	retractall('$aleph_search'(pclause,_)),
 7917	gc.
 7918
 7919clean_up_search:-
 7920	retractall('$aleph_search'(bad,_)),
 7921	retractall('$aleph_search'(best,_)),
 7922	retractall('$aleph_search'(best_label,_)),
 7923	retractall('$aleph_search'(clauseprior,_)),
 7924	retractall('$aleph_search'(covers,_)),
 7925	retractall('$aleph_search'(coversn,_)),
 7926	retractall('$aleph_search'(current,_)),
 7927	retractall('$aleph_search'(label,_)),
 7928	retractall('$aleph_search'(modes,_)),
 7929	retractall('$aleph_search'(nextnode,_)),
 7930	retractall('$aleph_search'(openlist,_)),
 7931	retractall('$aleph_search'(pclause,_)),
 7932	retractall('$aleph_search'(selected,_)),
 7933	retractall('$aleph_search_seen'(_,_)),
 7934	retractall('$aleph_search_expansion'(_,_,_,_)),
 7935	retractall('$aleph_search_gain'(_,_,_,_)),
 7936	retractall('$aleph_search_node'(_,_,_,_,_,_,_,_)).
 7937
 7938
 7939clean_up_examples:-
 7940	clean_up_examples(pos),
 7941	clean_up_examples(neg),
 7942	clean_up_examples(rand).
 7943
 7944clean_up_tree:-
 7945	retractall('$aleph_search'(tree,_)),
 7946	retractall('$aleph_search'(tree_startdistribution,_)),
 7947	retractall('$aleph_search'(tree_leaf,_)),
 7948	retractall('$aleph_search'(tree_lastleaf,_)),
 7949	retractall('$aleph_search'(tree_newleaf,_)),
 7950	retractall('$aleph_search'(tree_besterror,_)),
 7951	retractall('$aleph_search'(tree_gain,_)).
 7952
 7953clean_up_examples(Type):-
 7954	retractall('$aleph_global'(size,size(Type,_))),
 7955	retractall('$aleph_global'(atoms,atoms(Type,_))),
 7956	retractall('$aleph_global'(atoms_left,atoms_left(Type,_))),
 7957	retractall('$aleph_global'(last_example,last_example(Type,_))).
 7958
 7959clean_up_hypothesis:-
 7960        retractall('$aleph_global'(hypothesis,hypothesis(_,_,_,_))).
 7961
 7962depth_bound_call(G):-
 7963	'$aleph_global'(depth,set(depth,D)),
 7964	call_with_depth_bound(G,D).
 7965
 7966call_with_depth_bound((H:-B),D):-
 7967	!,
 7968	call_with_depth_bound((H,B),D).
 7969call_with_depth_bound((A,B),D):-
 7970	!,
 7971	depth_bound_call(A,D),
 7972	call_with_depth_bound(B,D).
 7973call_with_depth_bound(A,D):-
 7974	depth_bound_call(A,D).
 7975
 7976binom_lte(_,_,O,0.0):- O < 0, !.
 7977binom_lte(N,P,O,Prob):-
 7978        binom(N,P,O,Prob1),
 7979        O1 is O - 1,
 7980        binom_lte(N,P,O1,Prob2),
 7981        Prob is Prob1 + Prob2, !.
 7982
 7983binom(N,_,O,0.0):- O > N, !.
 7984binom(N,P,O,Prob):-
 7985        aleph_choose(N,O,C),
 7986        E1 is P^O,
 7987        P2 is 1 - P,
 7988        O2 is N - O,
 7989        E2 is P2^O2,
 7990        Prob is C*E1*E2, !.
 7991 
 7992aleph_choose(N,I,V):-
 7993        NI is N-I,
 7994        (NI > I -> pfac(N,NI,I,V) ; pfac(N,I,NI,V)).
 7995
 7996pfac(0,_,_,1).
 7997pfac(1,_,_,1).
 7998pfac(N,N,_,1).
 7999pfac(N,I,C,F):-
 8000        N1 is N-1,
 8001        C1 is C-1,
 8002        pfac(N1,I,C1,N1F),
 8003        F1 is N/C,
 8004        F is N1F*F1.
 8005
 8006% record_example(+Check,+Type,+Example,-N)
 8007%	records Example of type Type
 8008%	if Check = check, then checks to see if example exists
 8009%		also updates number of related databases accordingly
 8010%	if Check = nocheck then no check is done
 8011%	returns example number N and Flag
 8012%	if Flag = new then example is a new example of Type
 8013record_example(check,Type,Example,N1):- 
 8014	(once(example(N1,Type,Example)) -> true;
 8015		record_example(nocheck,Type,Example,N1),
 8016		(retract('$aleph_global'(atoms,atoms(Type,Atoms))) ->
 8017				true;
 8018				Atoms = []),
 8019		(retract('$aleph_global'(atoms_left,atoms_left(Type,AtomsLeft)))->
 8020				true;
 8021				AtomsLeft = []),
 8022		(retract('$aleph_global'(last_example,last_example(Type,_))) ->
 8023				true;
 8024				true),
 8025		update(Atoms,N1-N1,NewAtoms),
 8026		update(AtomsLeft,N1-N1,NewAtomsLeft),
 8027		asserta('$aleph_global'(atoms,atoms(Type,NewAtoms))),
 8028		asserta('$aleph_global'(atoms_left,atoms_left(Type,
 8029						NewAtomsLeft))),
 8030		asserta('$aleph_global'(last_example,last_example(Type,N1)))),
 8031	!.
 8032record_example(nocheck,Type,Example,N1):-
 8033	(retract('$aleph_global'(size,size(Type,N)))->
 8034		true;
 8035		N is 0),
 8036	N1 is N + 1,
 8037	asserta('$aleph_global'(size,size(Type,N1))),
 8038	(Type \= neg ->
 8039		setting(skolemvars,Sk1),
 8040		skolemize(Example,Fact,Body,Sk1,SkolemVars),
 8041		record_skolemized(Type,N1,SkolemVars,Fact,Body),
 8042		(Sk1 = SkolemVars -> true;
 8043			set(skolemvars,SkolemVars));
 8044		split_clause(Example,Head,Body),
 8045		record_nskolemized(Type,N1,Head,Body)), !.
 8046
 8047
 8048record_targetpred:-
 8049	retract('$aleph_local'(backpred,Name/Arity)),
 8050	once('$aleph_global'(determination,determination(Name/Arity,_))),
 8051	asserta('$aleph_global'(targetpred,targetpred(Name/Arity))),
 8052	record_testclause(Name/Arity),
 8053	fail.
 8054record_targetpred.
 8055
 8056check_recursive_calls:-
 8057	'$aleph_global'(targetpred,targetpred(Name/Arity)),
 8058	'$aleph_global'(determination,determination(Name/Arity,Name/Arity)),
 8059	record_recursive_sat_call(Name/Arity),
 8060	set(recursion,true),
 8061	fail.
 8062check_recursive_calls.
 8063
 8064check_posonly:-
 8065	'$aleph_global'(size,size(rand,N)), 
 8066	N > 0, !.
 8067check_posonly:-
 8068	setting(evalfn,posonly),
 8069	\+('$aleph_global'(modeh,modeh(_,_))),
 8070	p1_message('error'),
 8071	p_message('missing modeh declaration in posonly mode'), !,
 8072	fail.
 8073check_posonly:-
 8074	retractall('$aleph_global'(slp_count,_,_)),
 8075	retractall('$aleph_local'(slp_sample,_)),
 8076	retractall('$aleph_local'(slp_samplenum,_)),
 8077	setting(evalfn,posonly),
 8078	setting(gsamplesize,S),
 8079	condition_target,
 8080	'$aleph_global'(targetpred,targetpred(Name/Arity)),
 8081	gsample(Name/Arity,S), !.
 8082check_posonly.
 8083
 8084check_prune_defs:-
 8085	clause(prune(_),_), !,
 8086	set(prune_defs,true).
 8087check_prune_defs.
 8088
 8089check_auto_refine:-
 8090	(setting(construct_bottom,reduction);setting(construct_bottom,false)),
 8091	\+(setting(autorefine,true)), !,
 8092	(setting(refine,user) -> true; set(refine,auto)).
 8093check_auto_refine.
 8094
 8095check_user_search:-
 8096	setting(evalfn,user),
 8097	\+(cost_cover_required),
 8098	set(lazy_on_cost,true), !.
 8099check_user_search.
 8100
 8101check_abducibles:-
 8102	'$aleph_global'(abducible,abducible(Name/Arity)),
 8103	record_testclause(Name/Arity),
 8104	record_abclause(Name/Arity),
 8105	fail.
 8106check_abducibles.
 8107
 8108cost_cover_required:-
 8109	clause(cost(_,Label,Cost),Body),
 8110	vars_in_term([Label],[],Vars),
 8111	(occurs_in(Vars,p(Cost)); occurs_in(Vars,Body)), !.
 8112
 8113set_lazy_recalls:-
 8114	'$aleph_global'(lazy_evaluate,lazy_evaluate(Name/Arity)),
 8115	functor(Pred,Name,Arity),
 8116	% asserta('$aleph_global'(lazy_recall,lazy_recall(Name/Arity,1))),
 8117	asserta('$aleph_global'(lazy_recall,lazy_recall(Name/Arity,0))),
 8118	'$aleph_global'(mode,mode(Recall,Pred)),
 8119	'$aleph_global'(lazy_recall,lazy_recall(Name/Arity,N)),
 8120	(Recall = '*' -> RecallNum = 100; RecallNum = Recall),
 8121	RecallNum > N,
 8122	retract('$aleph_global'(lazy_recall,lazy_recall(Name/Arity,N))),
 8123	asserta('$aleph_global'(lazy_recall,lazy_recall(Name/Arity,RecallNum))),
 8124	fail.
 8125set_lazy_recalls.
 8126
 8127set_lazy_on_contradiction(_,_):-
 8128	'$aleph_global'(lazy_on_contradiction,set(lazy_on_contradiction,false)), !.
 8129set_lazy_on_contradiction(P,N):-
 8130	Tot is P + N,
 8131	Tot >= 100, !,
 8132	set(lazy_on_contradiction,true).
 8133set_lazy_on_contradiction(_,_).
 8134
 8135% The "pclause" trick: much more effective with the use of recorded/3
 8136% clause for testing partial clauses obtained in search
 8137% only needed when learning recursive theories or
 8138% proof_strategy is not restricted_sld.
 8139record_testclause(Name/Arity):-
 8140        functor(Head,Name,Arity),
 8141        Clause = (Head:-
 8142                        '$aleph_search'(pclause,pclause(Head,Body)),
 8143                        Body, !),
 8144        assertz(Clause).
 8145
 8146% The "pclause" trick for abducible predicates
 8147record_abclause(Name/Arity):-
 8148        functor(Head,Name,Arity),
 8149        Clause = (Head:-
 8150                        '$aleph_search'(abduced,pclause(Head,Body)),
 8151                        Body, !),
 8152        assertz(Clause).
 8153
 8154% clause for incorporating recursive calls into bottom clause
 8155% this is done by allowing calls to the positive examples
 8156record_recursive_sat_call(Name/Arity):-
 8157        functor(Head,Name,Arity),
 8158	Clause = (Head:-
 8159			'$aleph_global'(stage,set(stage,saturation)),
 8160			'$aleph_sat'(example,example(Num,Type)),
 8161			example(Num1,Type,Head),
 8162			Num1 \= Num, !),	% to prevent tautologies
 8163	assertz(Clause).
 8164
 8165skolemize((Head:-Body),SHead,SBody,Start,SkolemVars):-
 8166	!,
 8167	copy_term((Head:-Body),(SHead:-Body1)),
 8168	numbervars((SHead:-Body1),Start,SkolemVars),
 8169	goals_to_list(Body1,SBody).
 8170skolemize(UnitClause,Lit,[],Start,SkolemVars):-
 8171	copy_term(UnitClause,Lit),
 8172	numbervars(Lit,Start,SkolemVars).
 8173skolemize(UnitClause,Lit):-
 8174	skolemize(UnitClause,Lit,[],0,_).
 8175
 8176record_nskolemized(Type,N1,Head,true):-
 8177	!,
 8178	assertz(example(N1,Type,Head)).
 8179record_nskolemized(Type,N1,Head,Body):-
 8180	assertz((example(N1,Type,Head):-Body)).
 8181
 8182record_skolemized(Type,N1,SkolemVars,Head,Body):-
 8183	assertz(example(N1,Type,Head)),
 8184        functor(Head,Name,Arity),
 8185        update_backpreds(Name/Arity),
 8186	add_backs(Body),
 8187	add_skolem_types(SkolemVars,Head,Body).
 8188
 8189add_backs([]).
 8190add_backs([Lit|Lits]):-
 8191	asserta('$aleph_global'(back,back(Lit))),
 8192	functor(Lit,Name,Arity),
 8193	declare_dynamic(Name/Arity),
 8194	assertz(Lit),
 8195	add_backs(Lits).
 8196
 8197add_skolem_types(10000,_,_):- !.	% no new skolem variables
 8198add_skolem_types(_,Head,Body):-
 8199	add_skolem_types([Head]),
 8200	add_skolem_types(Body).
 8201
 8202add_skolem_types([]).
 8203add_skolem_types([Lit|Lits]):-
 8204	functor(Lit,PSym,Arity),
 8205	get_modes(PSym/Arity,L),
 8206	add_skolem_types1(L,Lit),
 8207	add_skolem_types(Lits).
 8208
 8209add_skolem_types1([],_).
 8210add_skolem_types1([Lit|Lits],Fact):-
 8211	split_args(Lit,_,I,O,C),
 8212	add_skolem_types2(I,Fact),
 8213	add_skolem_types2(O,Fact),
 8214	add_skolem_types2(C,Fact),
 8215	add_skolem_types1(Lits,Fact).
 8216
 8217add_skolem_types2([],_).
 8218add_skolem_types2([Pos/Type|Rest],Literal):-
 8219	tparg(Pos,Literal,Arg),
 8220	SkolemType =.. [Type,Arg],
 8221	('$aleph_global'(back,back(SkolemType))-> true;
 8222		asserta('$aleph_global'(back,back(SkolemType))),
 8223		asserta(SkolemType)),
 8224	add_skolem_types2(Rest,Literal).
 8225
 8226
 8227copy_args(_,_,Arg,Arity):-
 8228	Arg > Arity, !.
 8229copy_args(Lit,Lit1,Arg,Arity):-
 8230	arg(Arg,Lit,T),
 8231	arg(Arg,Lit1,T),
 8232	NextArg is Arg + 1,
 8233	copy_args(Lit,Lit1,NextArg,Arity).
 8234
 8235copy_iargs(0,_,_,_):- !.
 8236copy_iargs(Arg,Old,New,Arg):-
 8237        !,
 8238        Arg1 is Arg - 1,
 8239        copy_iargs(Arg1,Old,New,Arg).
 8240copy_iargs(Arg,Old,New,Out):-
 8241        arg(Arg,Old,Val),
 8242        arg(Arg,New,Val),
 8243        Arg1 is Arg - 1,
 8244        copy_iargs(Arg1,Old,New,Out).
 8245
 8246
 8247index_clause((Head:-true),NextClause,(Head)):-
 8248	!,
 8249	retract('$aleph_global'(last_clause,last_clause(ClauseNum))),
 8250	NextClause is ClauseNum + 1,
 8251	asserta('$aleph_global'(last_clause,last_clause(NextClause))).
 8252index_clause(Clause,NextClause,Clause):-
 8253	retract('$aleph_global'(last_clause,last_clause(ClauseNum))),
 8254	NextClause is ClauseNum + 1,
 8255	asserta('$aleph_global'(last_clause,last_clause(NextClause))).
 8256
 8257update_backpreds(Name/Arity):-
 8258	'$aleph_local'(backpred,Name/Arity), !.
 8259update_backpreds(Name/Arity):-
 8260	assertz('$aleph_local'(backpred,Name/Arity)).
 8261	
 8262reset_counts:-
 8263	retractall('$aleph_sat'(lastterm,_)),
 8264	retractall('$aleph_sat'(lastvar,_)),
 8265	asserta('$aleph_sat'(lastterm,0)),
 8266	asserta('$aleph_sat'(lastvar,0)), !.
 8267
 8268% reset the number of successes for a literal: cut to avoid useless backtrack
 8269reset_succ:-
 8270        retractall('$aleph_local'(last_success,_)),
 8271        asserta('$aleph_local'(last_success,0)), !.
 8272
 8273skolem_var(Var):-
 8274	atomic(Var), !,
 8275	name(Var,[36|_]).
 8276skolem_var(Var):-
 8277	gen_var(Num),
 8278	name(Num,L),
 8279	name(Var,[36|L]).
 8280
 8281gen_var(Var1):-
 8282	retract('$aleph_sat'(lastvar,Var0)), !,
 8283        Var1 is Var0 + 1,
 8284	asserta('$aleph_sat'(lastvar,Var1)).
 8285gen_var(0):-
 8286	asserta('$aleph_sat'(lastvar,0)).
 8287
 8288copy_var(OldVar,NewVar,Depth):-
 8289	gen_var(NewVar),
 8290	'$aleph_sat_vars'(OldVar,TNo,_,_),
 8291	asserta('$aleph_sat_vars'(NewVar,TNo,[],[])),
 8292	asserta('$aleph_sat_varscopy'(NewVar,OldVar,Depth)).
 8293
 8294gen_litnum(Lit1):-
 8295	retract('$aleph_sat'(lastlit,Lit0)), !,
 8296        Lit1 is Lit0 + 1,
 8297	asserta('$aleph_sat'(lastlit,Lit1)).
 8298gen_litnum(0):-
 8299	asserta('$aleph_sat'(lastlit,0)).
 8300
 8301gen_nlitnum(Lit1):-
 8302	retract('$aleph_sat'(lastnlit,Lit0)), !,
 8303        Lit1 is Lit0 - 1,
 8304	asserta('$aleph_sat'(lastnlit,Lit1)).
 8305gen_nlitnum(-1):-
 8306	asserta('$aleph_sat'(lastnlit,-1)).
 8307
 8308% generate a new feature number
 8309% provided it is less than the maximum number of features allowed
 8310gen_featurenum(Feature1):-
 8311        '$aleph_feature'(last_feature,Feature0), !,
 8312        Feature1 is Feature0 + 1,
 8313	setting(max_features,FMax),
 8314	Feature1 =< FMax,
 8315        retract('$aleph_feature'(last_feature,Feature0)), 
 8316        asserta('$aleph_feature'(last_feature,Feature1)).
 8317gen_featurenum(1):-
 8318        asserta('$aleph_feature'(last_feature,1)).
 8319
 8320gen_lits([],[]).
 8321gen_lits([Lit|Lits],[LitNum|Nums]):-
 8322	gen_litnum(LitNum),
 8323	asserta('$aleph_sat_litinfo'(LitNum,0,Lit,[],[],[])),
 8324	gen_lits(Lits,Nums).
 8325
 8326update_theory(ClauseIndex):-
 8327        retract('$aleph_global'(hypothesis,hypothesis(OldLabel,Hypothesis,
 8328				OldPCover,OldNCover))), 
 8329	index_clause(Hypothesis,ClauseIndex,Clause),
 8330        ('$aleph_global'(example_selected,example_selected(_,Seed))-> true;
 8331                PCover = [Seed-_|_]),
 8332	(setting(lazy_on_cost,true) ->
 8333        	nlits(Clause,L),
 8334		label_create(Clause,Label),
 8335        	extract_pos(Label,PCover),
 8336        	extract_neg(Label,NCover),
 8337        	interval_count(PCover,PC),
 8338        	interval_count(NCover,NC),
 8339		setting(evalfn,Evalfn),
 8340		complete_label(Evalfn,Clause,[PC,NC,L],NewLabel),
 8341        	assertz('$aleph_global'(theory,theory(ClauseIndex,
 8342					NewLabel/Seed,Clause,
 8343					PCover,NCover)));
 8344        	assertz('$aleph_global'(theory,theory(ClauseIndex,
 8345					OldLabel/Seed,Clause,
 8346					OldPCover,OldNCover)))),
 8347	add_clause_to_background(ClauseIndex).
 8348
 8349add_clause_to_background(ClauseIndex):-
 8350        '$aleph_global'(theory,theory(ClauseIndex,Label/_,Clause,_,_)),
 8351	(setting(minpos,PMin) -> true; PMin = 1),
 8352	Label = [PC,_,_,F|_],
 8353	PC >= PMin,
 8354	setting(minscore,MinScore),
 8355	F >= MinScore, !,
 8356        (retract('$aleph_global'(rules,rules(Rules)))->
 8357                asserta('$aleph_global'(rules,rules([ClauseIndex|Rules])));
 8358                asserta('$aleph_global'(rules,rules([ClauseIndex])))),
 8359	(setting(updateback,Update) -> true; Update = true),
 8360        (Update = true -> assertz(Clause); true),  !.
 8361add_clause_to_background(_).
 8362
 8363
 8364rm_seeds:-
 8365	update_theory(ClauseIndex), !,
 8366	'$aleph_global'(theory,theory(ClauseIndex,_,_,PCover,NCover)),
 8367	rm_seeds(pos,PCover),
 8368	(setting(evalfn,posonly) -> rm_seeds(rand,NCover); true),
 8369	'$aleph_global'(atoms_left,atoms_left(pos,PLeft)),
 8370	interval_count(PLeft,PL),
 8371	p1_message('atoms left'), p_message(PL),
 8372	!.
 8373rm_seeds.
 8374
 8375rm_seeds(pos,PCover):-
 8376	setting(construct_features,true),
 8377	setting(feature_construction,exhaustive), !,
 8378        retract('$aleph_global'(atoms_left,atoms_left(pos,OldIntervals))),
 8379        ('$aleph_global'(example_selected,example_selected(_,Seed))-> true;
 8380                PCover = [Seed-_|_]),
 8381        rm_seeds1([Seed-Seed],OldIntervals,NewIntervals),
 8382        assertz('$aleph_global'(atoms_left,atoms_left(pos,NewIntervals))).
 8383rm_seeds(Type,RmIntervals) :-
 8384        retract('$aleph_global'(atoms_left,atoms_left(Type,OldIntervals))),
 8385        rm_seeds1(RmIntervals,OldIntervals,NewIntervals),
 8386        assertz('$aleph_global'(atoms_left,atoms_left(Type,NewIntervals))).
 8387 
 8388rm_seeds1([],Done,Done).
 8389rm_seeds1([Start-Finish|Rest],OldIntervals,NewIntervals) :-
 8390        rm_interval(Start-Finish,OldIntervals,MidIntervals),!,
 8391        rm_seeds1(Rest,MidIntervals,NewIntervals).
 8392
 8393% update lower estimate on maximum size cover set for an atom
 8394update_coverset(Type,_):-
 8395        '$aleph_global'(hypothesis,hypothesis(Label,_,PCover,_)),
 8396	Label = [_,_,_,GainE|_],
 8397	arithmetic_expression_value(GainE,Gain),
 8398        worse_coversets(PCover,Type,Gain,Worse),
 8399        (Worse = [] -> true;
 8400                update_theory(NewClause),
 8401                update_coversets(Worse,NewClause,Type,Label)).
 8402
 8403% revise coversets of previous atoms
 8404worse_coversets(_,_,_,[]):-
 8405	\+('$aleph_global'(maxcover,set(maxcover,true))), !.
 8406worse_coversets([],_,_,[]).
 8407worse_coversets([Interval|Intervals],Type,Gain,Worse):-
 8408	worse_coversets1(Interval,Type,Gain,W1),
 8409	worse_coversets(Intervals,Type,Gain,W2),
 8410	aleph_append(W2,W1,Worse), !.
 8411
 8412worse_coversets1(Start-Finish,_,_,[]):-
 8413        Start > Finish, !.
 8414worse_coversets1(Start-Finish,Type,Gain,Rest):-
 8415        '$aleph_global'(max_set,max_set(Type,Start,Label1,_)),
 8416	Label1 = [_,_,_,Gain1E|_],
 8417	arithmetic_expression_value(Gain1E,Gain1),
 8418        Gain1 >= Gain, !,
 8419        Next is Start + 1,
 8420        worse_coversets1(Next-Finish,Type,Gain,Rest), !.
 8421worse_coversets1(Start-Finish,Type,Gain,[Start|Rest]):-
 8422        Next is Start + 1,
 8423        worse_coversets1(Next-Finish,Type,Gain,Rest), !.
 8424
 8425update_coversets([],_,_,_).
 8426update_coversets([Atom|Atoms],ClauseNum,Type,Label):-
 8427	(retract('$aleph_global'(max_set,max_set(Type,Atom,_,_)))->
 8428		true;
 8429		true),
 8430	asserta('$aleph_global'(max_set,max_set(Type,Atom,Label,ClauseNum))),
 8431	update_coversets(Atoms,ClauseNum,Type,Label), !.
 8432
 8433rm_intervals([],I,I).
 8434rm_intervals([I1|I],Intervals,Result):-
 8435	rm_interval(I1,Intervals,Intervals1), 
 8436	rm_intervals(I,Intervals1,Result), !.
 8437
 8438rm_interval(_,[],[]).
 8439rm_interval(I1,[Interval|Rest],Intervals):-
 8440	interval_intersection(I1,Interval,I2), !,
 8441	interval_subtract(Interval,I2,I3),
 8442	rm_interval(I1,Rest,I4),
 8443	aleph_append(I4,I3,Intervals).
 8444rm_interval(I1,[Interval|Rest],[Interval|Intervals]):-
 8445	rm_interval(I1,Rest,Intervals).
 8446
 8447% gen_sample(+Type,+N)
 8448% select N random samples from the set of examples uncovered. Type is one of pos/neg
 8449% if N = 0 returns first example in Set
 8450% resamples the same example R times where set(resample,R)
 8451gen_sample(Type,0):-
 8452	!,
 8453	'$aleph_global'(atoms_left,atoms_left(Type,[ExampleNum-_|_])),
 8454	retractall('$aleph_global'(example_selected,example_selected(_,_))),
 8455	p1_message('select example'), p_message(ExampleNum),
 8456	(setting(resample,Resample) -> true; Resample = 1),
 8457	gen_sample(Resample,Type,ExampleNum).
 8458gen_sample(Type,SampleSize):-
 8459	'$aleph_global'(atoms_left,atoms_left(Type,Intervals)),
 8460	% p1_message('select from'), p_message(Intervals),
 8461	interval_count(Intervals,AtomsLeft),
 8462	N is min(AtomsLeft,SampleSize),
 8463	assertz('$aleph_local'(sample_num,0)),
 8464	retractall('$aleph_global'(example_selected,example_selected(_,_))),
 8465	(setting(resample,Resample) -> true; Resample = 1),
 8466	repeat,
 8467	'$aleph_local'(sample_num,S1),
 8468	S is S1 + 1,
 8469	(S =< N ->
 8470		get_random(AtomsLeft,INum),
 8471		select_example(INum,0,Intervals,ExampleNum),
 8472		\+('$aleph_global'(example_selected,
 8473				example_selected(Type,ExampleNum))),
 8474		p1_message('select example'), p_message(ExampleNum),
 8475		retract('$aleph_local'(sample_num,S1)),
 8476		assertz('$aleph_local'(sample_num,S)),
 8477		gen_sample(Resample,Type,ExampleNum),
 8478		fail;
 8479		retract('$aleph_local'(sample_num,S1))), !.
 8480
 8481gen_sample(0,_,_):- !.
 8482gen_sample(R,Type,ExampleNum):-
 8483	assertz('$aleph_global'(example_selected,
 8484			example_selected(Type,ExampleNum))),
 8485	R1 is R - 1,
 8486	gen_sample(R1,Type,ExampleNum).
 8487
 8488select_example(Num,NumberSoFar,[Start-Finish|_],ExampleNum):-
 8489	Num =< NumberSoFar + Finish - Start + 1, !,
 8490	ExampleNum is Num - NumberSoFar + Start - 1.
 8491select_example(Num,NumberSoFar,[Start-Finish|Rest],ExampleNum):-
 8492	N1 is NumberSoFar + Finish - Start + 1,
 8493	select_example(Num,N1,Rest,ExampleNum).
 8494
 8495% get_random(+Last,-Num)
 8496% 	get a random integer between 1 and Last
 8497get_random(Last,INum):-
 8498	aleph_random(X),
 8499	INum1 is integer(X*Last + 0.5),
 8500	(INum1 = 0 ->
 8501		INum = 1;
 8502		(INum1 > Last ->
 8503			INum = Last;
 8504			INum = INum1
 8505		)
 8506	).
 8507
 8508% get_rrandom(+Last,-Num)
 8509% 	get a random floating point number between 1 and Last
 8510get_rrandom(Last,Num):-
 8511	aleph_random(X),
 8512	Num is X*Last.
 8513
 8514% distrib(+Interval,+Prob,-Distrib)
 8515%	generate discrete distribution Distrib
 8516%	by assigning all elements in Interval the probability Prob
 8517distrib(X-Y,_,[]):-  X > Y, !.
 8518distrib(X-Y,P,[P-X|D]):-
 8519	X1 is X + 1,
 8520	distrib(X1-Y,P,D).
 8521
 8522% draw_element(+D,-E)
 8523%	draw element E using distribution D
 8524%	D is a list specifying the probability of each element E
 8525%		in the form p1-e1, p2-e2, ... ,pn-en
 8526%	       	proportions pi are normalised to add to 1
 8527draw_element(D,E):-
 8528	normalise_distribution(D,Distr),
 8529	aleph_random(X),
 8530	draw_element(Distr,0,X,E).
 8531
 8532draw_element([P1-E1|T],CumProb,X,E):-
 8533	CumProb1 is CumProb + P1,
 8534	(X =< CumProb1 -> E = E1;
 8535		draw_element(T,CumProb1,X,E)).
 8536
 8537normalise_distribution(D,Distr):-
 8538	key_sum(D,Sum),
 8539	(0.0 is float(Sum) -> Distr = D;
 8540		normalise_distribution(D,Sum,D1),
 8541		keysort(D1,Distr)).
 8542
 8543key_sum([],0.0).
 8544key_sum([K1-_|T],Sum):-
 8545	key_sum(T,S1),
 8546	Sum is float(K1 + S1).
 8547
 8548normalise_distribution([],_,[]).
 8549normalise_distribution([K1-X1|T],Sum,[K2-X1|T1]):-
 8550	K2 is K1/Sum,
 8551	normalise_distribution(T,Sum,T1).
 8552
 8553% random_select(-Num,+List1,-List2)
 8554%       randomly remove an element Num from List1 to give List2
 8555random_select(X,[X],[]):- !.
 8556random_select(X,L,Left):-
 8557        length(L,N),
 8558        N > 0,
 8559        get_random(N,I),
 8560        aleph_remove_nth(I,L,X,Left).
 8561
 8562% random_nselect(+Num,+List1,-List2)
 8563%       randomly remove Num elements from List1 to give List2
 8564random_nselect(0,_,[]):- !.
 8565random_nselect(_,[],[]):- !.
 8566random_nselect(N,List1,[X|List2]):-
 8567        random_select(X,List1,Left),
 8568        N1 is N - 1,
 8569        random_nselect(N1,Left,List2).
 8570
 8571% random_select_from_intervals(-Num,+IList)
 8572% 	randomly select an element from an interval list
 8573random_select_from_intervals(N,IList):-
 8574	interval_count(IList,L),
 8575	get_random(L,X),
 8576	interval_select(X,IList,N).
 8577
 8578
 8579normal(Mean,Sigma,X):-
 8580	std_normal(X1),
 8581	X is Mean + Sigma*X1.
 8582
 8583get_normal(0,_,_,[]):- !.
 8584get_normal(N,Mean,Sigma,[X|Xs]):-
 8585        N > 0,
 8586        normal(Mean,Sigma,X),
 8587        N1 is N - 1,
 8588        get_normal(N1,Mean,Sigma,Xs).
 8589
 8590% Polar method for generating random variates
 8591% from a standard normal distribution.
 8592% From A.M. Law and W.D. Kelton, "Simulation Modeling and Analysis",
 8593% 	McGraw-Hill,2000
 8594std_normal(X):-
 8595	aleph_random(U1),
 8596	aleph_random(U2),
 8597	V1 is 2*U1 - 1,
 8598	V2 is 2*U2 - 1,
 8599	W is V1^2 + V2^2,
 8600	(W > 1 -> std_normal(X);
 8601		Y is sqrt((-2.0*log(W))/W),
 8602		X is V1*Y).
 8603
 8604% Approximate method for computing the chi-square value
 8605% given the d.f. and probability (to the right). Uses
 8606% a normal approximation and Monte-Carlo simulation.
 8607% The normal approximation used is the one proposed by
 8608% E.B. Wilson and M.M. Hilferty (1931). "The distribution of chi-square"
 8609%  	PNAS, 17, 684.
 8610% Monte-Carlo simulation uses 1000 trials.
 8611chi_square(DF,Prob,ChisqVal):-
 8612	DF > 0,
 8613	Mean is 1 - 2/(9*DF),
 8614	Sigma is sqrt(2/(9*DF)),
 8615	NTrials is 1000,
 8616	get_normal(NTrials,Mean,Sigma,X),
 8617	sort(X,Z),
 8618	ProbLeft is 1.0 - Prob,
 8619	Index is integer(ProbLeft*NTrials),
 8620	(Index > NTrials ->
 8621		aleph_remove_nth(NTrials,Z,Val,_);
 8622		aleph_remove_nth(Index,Z,Val,_)),
 8623	ChisqVal is DF*(Val^3).
 8624
 8625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 8626% L A B E L S   A N D    E V A L F N S
 8627% 
 8628
 8629label_create(Clause,Label):-
 8630        '$aleph_global'(last_example,last_example(pos,Last1)),
 8631	Type1 = pos,
 8632	(setting(evalfn,posonly) ->
 8633        	'$aleph_global'(last_example,last_example(rand,Last2)),
 8634		Type2 = rand;
 8635        	'$aleph_global'(last_example,last_example(neg,Last2)),
 8636		Type2 = neg),
 8637	label_create(Clause,Type1,[1-Last1],Type2,[1-Last2],Label).
 8638
 8639label_create(Type,Clause,Label):-
 8640        '$aleph_global'(last_example,last_example(Type,Last)),
 8641	label_create(Clause,Type,[1-Last],Label).
 8642
 8643label_create(Clause,Type1,Set1,Type2,Set2,Label):-
 8644        split_clause(Clause,Head,Body),
 8645	nlits((Head,Body),Length),
 8646        assertz('$aleph_search'(pclause,pclause(Head,Body))),
 8647	setting(depth,Depth),
 8648	setting(prooftime,Time),
 8649	setting(proof_strategy,Proof),
 8650        prove(Depth/Time/Proof,Type1,(Head:-Body),Set1,Cover1,_),
 8651        prove(Depth/Time/Proof,Type2,(Head:-Body),Set2,Cover2,_),
 8652	retractall('$aleph_search'(pclause,_)),
 8653        assemble_label(Cover1,Cover2,Length,Label), !.
 8654
 8655label_create(Clause,Type,Set,Label):-
 8656        split_clause(Clause,Head,Body),
 8657        assertz('$aleph_search'(pclause,pclause(Head,Body))),
 8658	setting(depth,Depth),
 8659	setting(prooftime,Time),
 8660	setting(proof_strategy,Proof),
 8661        prove(Depth/Time/Proof,Type,(Head:-Body),Set,Cover,_),
 8662	retractall('$aleph_search'(pclause,_)),
 8663	(Type = pos -> 
 8664        	assemble_label(Cover,unknown,unknown,Label);
 8665        	assemble_label(unknown,Cover,unknown,Label)).
 8666
 8667label_pcover(Label,P):-
 8668	extract_cover(pos,Label,P).
 8669label_ncover(Label,N):-
 8670	extract_cover(neg,Label,N).
 8671
 8672label_union([],Label,Label):- !.
 8673label_union(Label,[],Label):- !.
 8674label_union(Label1,Label2,Label):-
 8675        extract_cover(pos,Label1,Pos1),
 8676        extract_cover(pos,Label2,Pos2),
 8677        extract_cover(neg,Label1,Neg1),
 8678        extract_cover(neg,Label2,Neg2),
 8679        extract_length(Label1,L1),
 8680        extract_length(Label2,L2),
 8681        update_list(Pos2,Pos1,Pos),
 8682        update_list(Neg2,Neg1,Neg),
 8683        Length is L1 + L2,
 8684        list_to_intervals(Pos,PCover),
 8685        list_to_intervals(Neg,NCover),
 8686        assemble_label(PCover,NCover,Length,Label).
 8687
 8688label_print_examples(Type,Label):-
 8689        extract_cover(Type,Label,C),
 8690	examples(Type,C).
 8691
 8692label_print_eval([]):- !.
 8693label_print_eval(Label):-
 8694	Eval = coverage,
 8695	evalfn(Eval,Label,Val),
 8696	print_eval(Eval,Val).
 8697
 8698print_eval(Evalfn,Val):-
 8699	evalfn_name(Evalfn,Name),
 8700	p1_message(Name), p_message(Val).
 8701
 8702
 8703eval_rule(0,Label):-
 8704	'$aleph_global'(hypothesis,hypothesis(_,Clause,_,_)), !,
 8705	label_create(Clause,Label),
 8706	p_message('Rule 0'),
 8707	pp_dclause(Clause),
 8708	extract_count(pos,Label,PC),
 8709	extract_count(neg,Label,NC),
 8710	extract_length(Label,L),
 8711	label_print_eval([PC,NC,L]),
 8712	nl.
 8713eval_rule(ClauseNum,Label):-
 8714	integer(ClauseNum),
 8715	ClauseNum > 0,
 8716	'$aleph_global'(theory,theory(ClauseNum,_,Clause,_,_)),
 8717	!,
 8718	label_create(Clause,Label),
 8719	extract_count(pos,Label,PC),
 8720	extract_count(neg,Label,NC),
 8721	concat(['Rule ',ClauseNum],RuleTag),
 8722	(setting(evalfn,posonly) ->
 8723		concat(['Pos cover = ',PC,' Rand cover = ',NC],CoverTag);
 8724		concat(['Pos cover = ',PC,' Neg cover = ',NC],CoverTag)),
 8725	p1_message(RuleTag), p_message(CoverTag),
 8726	pp_dclause(Clause),
 8727	setting(verbosity,V),
 8728	(V >= 2 ->
 8729		p_message('positive examples covered'),
 8730		label_print_examples(pos,Label),
 8731		p_message('negative examples covered'),
 8732		label_print_examples(neg,Label);
 8733		true),
 8734	nl.
 8735eval_rule(_,_).
 8736
 8737
 8738evalfn(Label,Val):-
 8739	(setting(evalfn,Eval)->true;Eval=coverage),
 8740	evalfn(Eval,Label,Val).
 8741
 8742evalfn_name(compression,'compression').
 8743evalfn_name(coverage,'pos-neg').
 8744evalfn_name(accuracy,'accuracy').
 8745evalfn_name(wracc,'novelty').
 8746evalfn_name(laplace,'laplace estimate').
 8747evalfn_name(pbayes,'pseudo-bayes estimate').
 8748evalfn_name(auto_m,'m estimate').
 8749evalfn_name(mestimate,'m estimate').
 8750evalfn_name(mse,'mse').
 8751evalfn_name(posonly,'posonly bayes estimate').
 8752evalfn_name(entropy,'entropy').
 8753evalfn_name(gini,'gini value').
 8754evalfn_name(sd,'standard deviation').
 8755evalfn_name(user,'user defined cost').
 8756
 8757evalfn(compression,[P,N,L|_],Val):-
 8758	(P = -inf -> Val is -inf;
 8759        	Val is P - N - L + 1), !.
 8760evalfn(coverage,[P,N,_|_],Val):-
 8761	(P = -inf -> Val is -inf;
 8762		Val is P - N), !.
 8763evalfn(laplace,[P,N|_],Val):-
 8764	(P = -inf -> Val is 0.5;
 8765		Val is (P + 1) / (P + N + 2)), !.
 8766% the evaluation function below is due to Steve Moyle's implementation
 8767% of the work by Lavrac, Flach and Zupan
 8768evalfn(wracc,[P,N|_],Val):-
 8769	('$aleph_search'(clauseprior,Total-[P1-pos,_]) ->
 8770		Val is P/Total - (P1/Total)*((P+N)/Total);
 8771		Val is -0.25), !.
 8772evalfn(entropy,[P,N|_],Val):-
 8773	(P = -inf ->  Val is 1.0;
 8774		((P is 0); (N is 0) -> Val is 0.0;
 8775			Total is P + N,
 8776			P1 is P/Total,
 8777			Q1 is 1-P1,
 8778			Val is -(P1*log(P1) + Q1*log(Q1))/log(2)
 8779		)
 8780	), !.
 8781evalfn(gini,[P,N|_],Val):-
 8782	(P = -inf -> Val is 1.0;
 8783		Total is P + N,
 8784		P1 is P/Total,
 8785		Val is 2*P1*(1-P1)), !.
 8786evalfn(accuracy,[P,N|_],Val):-
 8787	(P = -inf -> Val is 0.5;
 8788		Val is P / (P + N)), !.
 8789% the evaluation functions below are due to James Cussens
 8790evalfn(pbayes,[P,N|_],Val):-
 8791        (P = -inf -> Val is 0.5;
 8792                Acc is P/(P+N),
 8793                setting(prior,PriorD),
 8794		normalise_distribution(PriorD,NPriorD),
 8795		aleph_member1(Prior-pos,NPriorD),
 8796                (0 is Prior-Acc ->
 8797                    Val=Prior;
 8798                K is (Acc*(1 - Acc)) / ((Prior-Acc)^2 ),
 8799                Val is (P + K*Prior) / (P + N + K))), !.
 8800evalfn(posonly,[P,0,L|_],Val):-
 8801        '$aleph_global'(size,size(rand,RSize)),
 8802        Val is log(P) + log(RSize+2.0) - (L+1)/P, !.
 8803evalfn(auto_m,[P,N|_],Val):-
 8804        (P = -inf -> Val is 0.5;
 8805                Cover is P + N,
 8806                setting(prior,PriorD),
 8807		normalise_distribution(PriorD,NPriorD),
 8808		aleph_member1(Prior-pos,NPriorD),
 8809                K is sqrt(Cover),
 8810                Val is (P + K*Prior) / (Cover+K)), !.
 8811evalfn(mestimate,[P,N|_],Val):-
 8812        (P = -inf -> Val is 0.5;
 8813                Cover is P + N,
 8814                setting(prior,PriorD),
 8815		normalise_distribution(PriorD,NPriorD),
 8816		aleph_member1(Prior-pos,NPriorD),
 8817                (setting(m,M) -> K = M; K is sqrt(Cover)),
 8818                Val is (P + K*Prior) / (Cover+K)), !.
 8819evalfn(_,_,X):- X is -inf.
 8820
 8821
 8822assemble_label(P,N,L,[P,N,L]).
 8823
 8824extract_cover(pos,[P,_,_],P1):-
 8825        intervals_to_list(P,P1), !.
 8826extract_cover(neg,[_,N,_],N1):-
 8827        intervals_to_list(N,N1),!.
 8828extract_cover(_,[]).
 8829
 8830extract_count(pos,[P,_,_],P1):-
 8831	interval_count(P,P1), !.
 8832extract_count(neg,[_,N,_],N1):-
 8833	interval_count(N,N1), !.
 8834extract_count(neg,_,0).
 8835
 8836
 8837extract_pos([P|_],P).
 8838extract_neg([_,N|_],N).
 8839extract_length([_,_,L|_],L).
 8840
 8841get_start_label(_,[0,0,0,F]):-
 8842	(setting(interactive,true); setting(search,ic)), !,
 8843	F is -inf.
 8844get_start_label(user,[1,0,2,F]):- !, F is -inf.
 8845get_start_label(entropy,[1,0,2,-0.5]):- !.
 8846get_start_label(gini,[1,0,2,-0.5]):- !.
 8847get_start_label(wracc,[1,0,2,-0.25]):- !.
 8848get_start_label(Evalfn,[1,0,2,Val]):-
 8849	evalfn(Evalfn,[1,0,2],Val).
 8850
 8851
 8852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 8853% I / O   S T U F F
 8854
 8855% read_all(+Prefix)
 8856%	read background and examples
 8857read_all(Prefix):-
 8858	read_all(Prefix,Prefix,Prefix).
 8859
 8860% read_all/2 and read_all/3 largely
 8861% provided by Stasinos Konstantopoulos and Mark Reid
 8862read_all(BPrefix,EPrefix):-
 8863	read_all(BPrefix,EPrefix,EPrefix).
 8864
 8865read_all(Back,Pos,Neg):-
 8866	clean_up,
 8867	reset,
 8868	read_background(Back),
 8869	read_examples(Pos,Neg), 	
 8870	record_targetpred, 	
 8871	check_recursive_calls,
 8872	check_prune_defs,
 8873	check_user_search,
 8874	check_posonly,
 8875	check_auto_refine,
 8876	check_abducibles.
 8877
 8878read_background(Back):-
 8879	construct_name(background,Back,File),
 8880	aleph_reconsult(File),
 8881	broadcast(background(loaded)).
 8882
 8883read_examples(Pos,Neg):-
 8884	(setting(train_pos,PosF) ->
 8885		set(use_file_extensions,false),
 8886		read_examples_files(pos,PosF,_),
 8887		noset(use_file_extensions);
 8888		read_examples_files(pos,Pos,PosF),
 8889		set(train_pos,PosF)
 8890	),
 8891	(setting(train_neg,NegF) ->
 8892		set(use_file_extensions,false),
 8893		read_examples_files(neg,NegF,_),
 8894		noset(use_file_extensions);
 8895		read_examples_files(neg,Neg,NegF),
 8896		set(train_neg,NegF)
 8897	),
 8898	'$aleph_global'(size,size(pos,P)),
 8899	'$aleph_global'(size,size(neg,N)),
 8900	set_lazy_recalls,
 8901	(setting(prior,_) -> true;
 8902		normalise_distribution([P-pos,N-neg],Prior),
 8903		set(prior,Prior)
 8904	),
 8905	reset_counts,
 8906	asserta('$aleph_global'(last_clause,last_clause(0))),
 8907	broadcast(examples(loaded)).
 8908
 8909read_examples_files(Type,Name,F):-
 8910	clean_up_examples(Type),
 8911	asserta('$aleph_global'(size,size(Type,0))),
 8912	(Name = [_|_] ->
 8913		read_examples_from_files(Name,Type,F);
 8914		read_examples_from_file(Type,Name,F)),
 8915	'$aleph_global'(size,size(Type,N)),
 8916	(N > 0 -> Ex = [1-N]; Ex = []),
 8917	asserta('$aleph_global'(atoms,atoms(Type,Ex))),
 8918	asserta('$aleph_global'(atoms_left,atoms_left(Type,Ex))),
 8919	asserta('$aleph_global'(last_example,last_example(Type,N))).
 8920
 8921read_examples_from_files([],_,[]).
 8922read_examples_from_files([Name|Files],Type,[FileName|FileNames]):-
 8923	read_examples_from_file(Type,Name,FileName),
 8924	read_examples_from_files(Files,Type,FileNames).
 8925
 8926read_examples_from_file(Type,Name,File):-
 8927	construct_name(Type,Name,File),
 8928	(aleph_open(File,read,Stream) ->
 8929		concat(['consulting ',Type, ' examples'],Mess),
 8930		p1_message(Mess), p_message(File);
 8931		p1_message('cannot open'), p_message(File),
 8932		fail),
 8933	repeat,
 8934	read(Stream,Example),
 8935	(Example=end_of_file-> close(Stream);
 8936		record_example(nocheck,Type,Example,_),
 8937		fail),
 8938	!.
 8939read_examples_from_file(_,_,'?').
 8940
 8941construct_name(_,Name,Name):-
 8942	setting(use_file_extensions,false), !.
 8943construct_name(Type,Prefix,Name):-
 8944	name(Prefix,PString),
 8945	file_extension(Type,SString),
 8946	aleph_append(SString,PString,FString),
 8947	name(Name,FString).
 8948
 8949file_extension(pos,Suffix):- name('.f',Suffix).
 8950file_extension(neg,Suffix):- name('.n',Suffix).
 8951file_extension(background,Suffix):- name('.b',Suffix).
 8952
 8953
 8954%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 8955% M I S C.   D E F I N I T I O N S
 8956
 8957execute(C):-
 8958	system(C), !.
 8959execute(_).
 8960
 8961% store critical values of current search state
 8962store(searchstate):-
 8963	!,
 8964	retractall('$aleph_global'(save,save(searchstate,_))),
 8965	('$aleph_global'(atoms_left,atoms_left(pos,PosLeft)) ->
 8966		asserta('$aleph_global'(save,
 8967				save(searchstate,atoms_left(pos,PosLeft))));
 8968		true),
 8969	('$aleph_global'(atoms_left,atoms_left(neg,NegLeft)) ->
 8970		asserta('$aleph_global'(save,
 8971				save(searchstate,atoms_left(neg,NegLeft))));
 8972		true),
 8973	('$aleph_global'(size,size(pos,PSize)) ->
 8974		asserta('$aleph_global'(save,
 8975				save(searchstate,size(pos,PSize))));
 8976		true),
 8977	('$aleph_global'(size,size(neg,NSize)) ->
 8978		asserta('$aleph_global'(save,
 8979				save(searchstate,size(neg,NSize))));
 8980		true),
 8981	('$aleph_global'(noise,set(noise,Noise)) ->
 8982		asserta('$aleph_global'(save,
 8983				save(searchstate,set(noise,Noise))));
 8984		true),
 8985	('$aleph_global'(minacc,set(minacc,MinAcc)) ->
 8986		asserta('$aleph_global'(save,
 8987				save(searchstate,set(minacc,MinAcc))));
 8988		true).
 8989
 8990% store current bottom clause
 8991store(bottom):-
 8992	!,
 8993	('$aleph_global'(store_bottom,set(store_bottom,true)) ->
 8994		store_bottom;
 8995		true).
 8996
 8997store(Parameter):-
 8998	('$aleph_global'(Parameter,set(Parameter,Value)) -> true; Value = unknown),
 8999	retractall('$aleph_global'(save,save(Parameter,_))),
 9000	asserta('$aleph_global'(save,save(Parameter,Value))).
 9001
 9002% store values of a list of parameters
 9003store_values([]).
 9004store_values([Parameter|T]):-
 9005	store(Parameter),
 9006	store_values(T).
 9007
 9008% store all relevant info related to current bottom
 9009%	details are stored in 5 idbs:
 9010%	1. bottom: points to 2 other idbs sat_X_n and lits_X_N
 9011%	2. sat_X_N: where X is the type of the current example and N the number 
 9012%		this contains misc stuff recorded by sat/2 for use by reduce/1
 9013%	3. lits_X_N: contains the lits in bottom
 9014%	4. ovars_X_N: contains output vars of lits in bottom
 9015%	5. ivars_X_N: contains input vars of lits in bottom
 9016store_bottom:-
 9017	bottom_key(Num,Type,Key,true),
 9018	asserta('$aleph_sat'(stored,stored(Num,Type,Key))),
 9019	'$aleph_sat'(lastterm,LastTerm),
 9020	asserta('$aleph_sat'(lasterm,Key,LastTerm)),
 9021	'$aleph_sat'(lastvar,LastVar),
 9022	asserta('$aleph_sat'(lastvar,Key,LastVar)),
 9023	'$aleph_sat'(botsize,BotSize),
 9024	asserta('$aleph_sat'(botsize,Key,BotSize)),
 9025	'$aleph_sat'(lastlit,LastLit),
 9026	asserta('$aleph_sat'(lastlit,Key,LastLit)),
 9027	'$aleph_sat'(hovars,HOVars),
 9028	asserta('$aleph_sat'(hovars,Key,HOVars)),
 9029	'$aleph_sat'(hivars,HIVars),
 9030	asserta('$aleph_sat'(hivars,Key,HIVars)),
 9031	'$aleph_sat'(eq,Eq),
 9032	asserta('$aleph_sat'(eq,Key,Eq)),
 9033	'$aleph_sat_ivars'(Lit,IVars),
 9034	asserta('$aleph_sat_ivars'(Lit,Key,IVars)),
 9035	'$aleph_sat_ovars'(Lit,OVars),
 9036	asserta('$aleph_sat_ovars'(Lit,Key,OVars)),
 9037	'$aleph_sat_litinfo'(Lit,Depth,Atom,I,O,D),
 9038	asserta('$aleph_sat_litinfo'(Lit,Key,Depth,Atom,I,O,D)),
 9039	fail.
 9040store_bottom.
 9041	
 9042
 9043reinstate(searchstate):-
 9044	!,
 9045	retractall('$aleph_global'(atoms_left,atoms_left(_,_))),
 9046	retractall('$aleph_global'(size,size(_,_))),
 9047	('$aleph_global'(save,save(searchstate,atoms_left(pos,PosLeft))) ->
 9048		asserta('$aleph_global'(atoms_left,atoms_left(pos,PosLeft)));
 9049		true),
 9050	('$aleph_global'(save,save(searchstate,atoms_left(neg,NegLeft))) ->
 9051		asserta('$aleph_global'(atoms_left,atoms_left(neg,NegLeft)));
 9052		true),
 9053	('$aleph_global'(save,save(searchstate,size(pos,PSize))) ->
 9054		asserta('$aleph_global'(size,size(pos,PSize)));
 9055		true),
 9056	('$aleph_global'(save,save(searchstate,size(neg,NSize))) ->
 9057		asserta('$aleph_global'(size,size(neg,NSize)));
 9058		true),
 9059	('$aleph_global'(save,save(searchstate,set(noise,Noise))) ->
 9060		set(noise,Noise);
 9061		true),
 9062	('$aleph_global'(save,save(searchstate,set(minacc,MinAcc))) ->
 9063		set(minacc,MinAcc);
 9064		true),
 9065	retractall('$aleph_global'(save,save(searchstate,_))).
 9066reinstate(Parameter):-
 9067	retract('$aleph_global'(save,save(Parameter,Value))), !,
 9068	(Value = unknown -> noset(Parameter); set(Parameter,Value)).
 9069reinstate(_).
 9070
 9071% reinstate list of values of parameters
 9072reinstate_values([]).
 9073reinstate_values([Parameter|T]):-
 9074	reinstate(Parameter),
 9075	reinstate_values(T).
 9076
 9077% reinstate all saved values
 9078reinstate_values:-
 9079	reinstate_file_streams,
 9080	'$aleph_global'(save,save(_,_)), 
 9081	repeat,
 9082	retract('$aleph_global'(save,save(Parameter,Value))), 
 9083	(Value = unknown -> noset(Parameter) ; set(Parameter,Value)),
 9084	\+('$aleph_global'(save,save(_,_))),
 9085	!.
 9086reinstate_values.
 9087
 9088reinstate_file_streams:-
 9089	setting(recordfile,File),
 9090	set(recordfile,File),
 9091	fail.
 9092reinstate_file_streams:-
 9093	setting(goodfile,File),
 9094	set(goodfile,File),
 9095	fail.
 9096reinstate_file_streams.
 9097
 9098
 9099% bottom_key(?N,?T,-Key,-Flag)
 9100%	returns key that indexes bottom clause info for example N of type T
 9101%	Flag is one of "true" or "false" depending on whether bottom
 9102%	requires storing
 9103bottom_key(N,T,Key,Flag):-
 9104	((var(N),var(T)) ->
 9105		'$aleph_sat'(example,example(N,T));
 9106		true),
 9107	(setting(store_bottom,true) ->
 9108		('$aleph_sat'(stored,stored(N,T,Key)) ->
 9109			Flag = false;
 9110			concat([T,'_',N],Key),
 9111			Flag = true
 9112		);
 9113		Key = false,
 9114		Flag = false).
 9115
 9116set(Variable,Value):-
 9117	check_setting(Variable,Value),
 9118	(Value = inf -> V is inf;
 9119		(Value = +inf -> V is inf;
 9120			(Value = -inf -> V is -inf; V = Value)
 9121		)
 9122	),
 9123	retractall('$aleph_global'(Variable,set(Variable,_))),
 9124	assertz('$aleph_global'(Variable,set(Variable,V))),
 9125	broadcast(set(Variable,V)),
 9126	special_consideration(Variable,Value).
 9127
 9128setting(Variable,Value):-
 9129	nonvar(Variable), 
 9130	'$aleph_global'(Variable,set(Variable,Value1)), !,
 9131	Value = Value1.
 9132setting(Variable,Value):-
 9133	default_setting(Variable,Value).
 9134
 9135noset(Variable):-
 9136	nonvar(Variable),
 9137        retract('$aleph_global'(Variable,set(Variable,Value))), !,
 9138	rm_special_consideration(Variable,Value),
 9139	set_default(Variable).
 9140noset(_).
 9141
 9142man(M):-
 9143	aleph_manual(M).
 9144
 9145determinations(Pred1,Pred2):-
 9146        '$aleph_global'(determination,determination(Pred1,Pred2)).
 9147
 9148determination(Pred1,Pred2):-
 9149	nonvar(Pred1),
 9150	'$aleph_global'(determination,determination(Pred1,Pred2)), !.
 9151determination(Pred1,Pred2):-
 9152	noset(autorefine),
 9153	assertz('$aleph_global'(determination,determination(Pred1,Pred2))),
 9154	(nonvar(Pred1) ->
 9155		update_backpreds(Pred1);
 9156		true).
 9157
 9158abducible(Name/Arity):-
 9159	assertz('$aleph_global'(abducible,abducible(Name/Arity))).
 9160
 9161commutative(Name/Arity):-
 9162	assertz('$aleph_global'(commutative,commutative(Name/Arity))).
 9163
 9164symmetric(Name/Arity):-
 9165	assertz('$aleph_global'(symmetric,symmetric(Name/Arity))).
 9166
 9167lazy_evaluate(Name/Arity):-
 9168        assertz('$aleph_global'(lazy_evaluate,lazy_evaluate(Name/Arity))).
 9169
 9170model(Name/Arity):-
 9171        assertz('$aleph_global'(model,model(Name/Arity))).
 9172
 9173positive_only(Name/Arity):-
 9174	assertz('$aleph_global'(positive_only,positive_only(Name/Arity))).
 9175
 9176mode(Recall,Pred):-
 9177	modeh(Recall,Pred),
 9178	modeb(Recall,Pred).
 9179
 9180modes(N/A,Mode):-
 9181        Mode = modeh(_,Pred),
 9182        '$aleph_global'(modeh,Mode),
 9183        functor(Pred,N,A).
 9184modes(N/A,Mode):-
 9185        Mode = modeb(_,Pred),
 9186        '$aleph_global'(modeb,Mode),
 9187        functor(Pred,N,A).
 9188
 9189modeh(Recall,Pred):-
 9190	('$aleph_global'(mode,mode(Recall,Pred)) -> true;
 9191		noset(autorefine),
 9192		assertz('$aleph_global'(modeh,modeh(Recall,Pred))),
 9193		assertz('$aleph_global'(mode,mode(Recall,Pred))),
 9194        	functor(Pred,Name,Arity),
 9195        	update_backpreds(Name/Arity)).
 9196
 9197modeb(Recall,Pred):-
 9198	('$aleph_global'(modeb,modeb(Recall,Pred)) -> true;
 9199		noset(autorefine),
 9200		assertz('$aleph_global'(modeb,modeb(Recall,Pred))),
 9201		('$aleph_global'(mode,mode(Recall,Pred)) -> true;
 9202			assertz('$aleph_global'(mode,mode(Recall,Pred))))).
 9203
 9204% add_determinations(+PSym,Stratified)
 9205% add determination declarations for a background predicate
 9206% these are obtained from the determinations of the target predicate
 9207% If Stratified is true then only stratified definitions are allowed
 9208add_determinations(PSym,Stratified):-
 9209	'$aleph_global'(targetpred,targetpred(Target)),
 9210	determinations(Target,OtherPred),
 9211	(Stratified = true -> OtherPred \= Target; true),
 9212	determination(PSym,OtherPred),
 9213	fail.
 9214add_determinations(_,_).
 9215
 9216% add_modes(+PSym)
 9217% add modes declarations for a (new) predicate
 9218% these are obtained from the modes of the target predicate
 9219add_modes(Name/_):-
 9220	'$aleph_global'(targetpred,targetpred(Target)),
 9221	modes(Target,Mode),
 9222	Mode =.. [ModeType,Recall,TargetMode],
 9223	TargetMode =.. [_|Args],
 9224	PredMode =.. [Name|Args],
 9225	NewMode =.. [ModeType,Recall,PredMode],
 9226	call(NewMode),
 9227	fail.
 9228add_modes(_).
 9229
 9230feature(Id,Feature):-
 9231	'$aleph_feature'(feature,feature(Id,_,_,Template,Body)), 
 9232	Feature = (Template:-Body).
 9233
 9234gen_feature(Feature,Label,Class):-
 9235	nonvar(Feature), !,
 9236	gen_featurenum(Id),
 9237	split_clause(Feature,Template,Body),
 9238	assertz('$aleph_feature'(feature,feature(Id,Label,Class,Template,Body))).
 9239
 9240show(settings):-
 9241	nl,
 9242	p_message('settings'),
 9243	findall(P-V,'$aleph_global'(P,set(P,V)),L),
 9244	sort(L,L1),
 9245	aleph_member(Parameter-Value,L1),
 9246        tab(8), write(Parameter=Value), nl,
 9247        fail.
 9248show(determinations):-
 9249	nl,
 9250	p_message('determinations'),
 9251	show_global(determination,determination(_,_)).
 9252show(modes):-
 9253	nl,
 9254	p_message('modes'),
 9255	show_global(mode,mode(_,_)).
 9256show(modehs):-
 9257	nl,
 9258	p_message('modehs'),
 9259	show_global(modeh,modeh(_,_)).
 9260show(modebs):-
 9261	nl,
 9262	p_message('modebs'),
 9263	show_global(modeb,modeb(_,_)).
 9264show(sizes):-
 9265	nl,
 9266	p_message('sizes'),
 9267	show_global(size,size(_,_)).
 9268show(bottom):-
 9269	nl,
 9270	p_message('bottom clause'),
 9271	setting(verbosity,V),
 9272	V > 0,
 9273	'$aleph_sat'(lastlit,Last),
 9274	get_clause(1,Last,[],FlatClause),
 9275	pp_dlist(FlatClause).
 9276show(theory):-
 9277        nl,
 9278        p_message('theory'),
 9279        nl,
 9280        '$aleph_global'(rules,rules(L)),
 9281        aleph_reverse(L,L1),
 9282        aleph_member(ClauseNum,L1),
 9283	'$aleph_global'(theory,theory(ClauseNum,_,_,_,_)),
 9284	eval_rule(ClauseNum,_),
 9285	% pp_dclause(Clause),
 9286        fail.
 9287show(theory):-
 9288	get_performance.
 9289show(pos):-
 9290	nl,
 9291	p_message('positives'),
 9292	store(greedy),
 9293	examples(pos,_),
 9294	reinstate(greedy),
 9295	fail.
 9296show(posleft):-
 9297	nl,
 9298	p_message('positives left'),
 9299        example(_,pos,Atom),
 9300	\+(Atom),
 9301        write(Atom), write('.'), nl,
 9302	fail.
 9303show(neg):-
 9304	nl,
 9305	p_message('negatives'),
 9306	store(greedy),
 9307	examples(neg,_),
 9308	reinstate(greedy),
 9309	fail.
 9310show(rand):-
 9311	nl,
 9312	p_message('random'),
 9313	examples(rand,_),
 9314	fail.
 9315show(uspec):-
 9316	nl,
 9317	p_message('uspec'),
 9318	examples(uspec,_),
 9319	fail.
 9320show(gcws):-
 9321	nl,
 9322	p_message('gcws hypothesis'),
 9323	'$aleph_search'(gcwshyp,hypothesis(_,C,_,_)),
 9324	pp_dclause(C),
 9325	fail.
 9326show(abgen):-
 9327	nl,
 9328	p_message('abduced hypothesis'),
 9329	'$aleph_search'(abgenhyp,hypothesis(_,AbGen,_,_)),
 9330	aleph_member(C,AbGen),
 9331	pp_dclause(C),
 9332	fail.
 9333show(hypothesis):-
 9334	setting(portray_hypothesis,Pretty),
 9335	aleph_portray(hypothesis,Pretty),
 9336	fail.
 9337show(search):-
 9338	setting(portray_search,Pretty),
 9339	aleph_portray(search,Pretty).
 9340show(good):-
 9341	setting(good,true),
 9342	nl,
 9343        p_message('good clauses'),
 9344        (setting(minscore,FMin) -> true; FMin is -inf),
 9345        setting(evalfn,Evalfn),
 9346	'$aleph_good'(_,Label,Clause),
 9347	Label = [_,_,_,F|_],
 9348	F >= FMin,
 9349	pp_dclause(Clause),
 9350	show_stats(Evalfn,Label),
 9351	fail.
 9352show(good):-
 9353	setting(good,true),
 9354	setting(goodfile,File),
 9355	aleph_open(File,read,Stream),
 9356        (setting(minscore,FMin) -> true; FMin is -inf),
 9357        setting(evalfn,Evalfn),
 9358	repeat,
 9359	read(Stream,Fact),
 9360	(Fact = '$aleph_good'(_,Label,Clause) ->
 9361		Label = [_,_,_,F|_],
 9362		F >= FMin,
 9363        	show_stats(Evalfn,Label),
 9364        	pp_dclause(Clause),
 9365		fail;
 9366		close(Stream), !
 9367	).
 9368show(features):-
 9369        setting(evalfn,Evalfn),
 9370	('$aleph_feature'(feature,_) -> true;
 9371		gen_features),
 9372        p_message('features from good clauses'),
 9373	'$aleph_feature'(feature,feature(Id,Label,_,Head,Body)),
 9374	show_stats(Evalfn,Label),
 9375        pp_dclause(feature(Id,(Head:-Body))),
 9376	fail.
 9377show(constraints):-
 9378	setting(good,true),
 9379	nl,
 9380	p_message('constraints'),
 9381	setting(noise,N),
 9382	FMin is -N,
 9383	'$aleph_good'(_,Label,Clause),
 9384	split_clause(Clause,false,_),
 9385	Label = [_,_,_,F],
 9386	F >= FMin,
 9387        pp_dclause(Clause),
 9388        show_stats(coverage,Label),
 9389	fail.
 9390show(constraints):-
 9391	show(false/0).
 9392show(Name/Arity):-
 9393	functor(Pred,Name,Arity),
 9394	current_predicate(Name,Pred),
 9395        nl,
 9396        p1_message('definition'), p_message(Name/Arity),
 9397	clause(Pred,Body),
 9398	\+(in(Body,'$aleph_search'(pclause,pclause(_,_)))),
 9399	pp_dclause((Pred:-Body)),
 9400	fail.
 9401show(train_pos):-
 9402	setting(portray_examples,Pretty),
 9403	aleph_portray(train_pos,Pretty).
 9404show(train_neg):-
 9405	setting(portray_examples,Pretty),
 9406	aleph_portray(train_neg,Pretty).
 9407show(test_pos):-
 9408	setting(portray_examples,Pretty),
 9409	aleph_portray(test_pos,Pretty).
 9410show(test_neg):-
 9411	setting(portray_examples,Pretty),
 9412	aleph_portray(test_neg,Pretty).
 9413show(_).
 9414
 9415settings:-
 9416	show(settings).
 9417
 9418% examples(?Type,?List)
 9419% show all examples numbers in List of Type
 9420examples(Type,List):-
 9421	setting(portray_literals,Pretty),
 9422        example(Num,Type,Atom),
 9423        aleph_member1(Num,List),
 9424	aleph_portray(Atom,Pretty), write('.'), nl,
 9425        fail.
 9426examples(_,_).
 9427
 9428% bottom(-Clause)
 9429% 	returns current bottom clause
 9430bottom(Clause):-
 9431	'$aleph_sat'(lastlit,Last), 
 9432	get_clause(1,Last,[],ClauseList),
 9433	list_to_clause(ClauseList,Clause).
 9434
 9435% posleft(-List)
 9436%	returns positive examples left to be covered
 9437posleft(PList):-
 9438	'$aleph_global'(atoms_left,atoms_left(pos,PosLeft)),
 9439	intervals_to_list(PosLeft,PList).
 9440
 9441% write_rules/0 due to Mark Reid
 9442write_rules:-
 9443	setting(rulefile,File),
 9444	write_rules(File), !.
 9445write_rules.
 9446
 9447write_features:-
 9448	setting(featurefile,File),
 9449	write_features(File), !.
 9450write_features.
 9451
 9452write_rules(File):-
 9453        aleph_open(File,write,Stream),
 9454        set_output(Stream),
 9455        '$aleph_global'(rules,rules(L)),
 9456        aleph_reverse(L,L1),
 9457        write_rule(L1),
 9458        flush_output(Stream),
 9459        set_output(user_output).
 9460
 9461write_rule(Rules):-
 9462        aleph_member(RuleId,Rules),
 9463        '$aleph_global'(theory,theory(RuleId,_,Rule,_,_)),
 9464        pp_dclause(Rule),
 9465        fail.
 9466write_rule(_).
 9467
 9468write_features(File):-
 9469        aleph_open(File,write,Stream),
 9470        set_output(Stream),
 9471	listing('$aleph_feature'/2),
 9472        close(Stream),
 9473        set_output(user_output).
 9474write_features(_).
 9475
 9476
 9477best_hypothesis(Head1,Body1,[P,N,L]):-
 9478	'$aleph_search'(selected,selected([P,N,L|_],Clause,_,_)),
 9479	split_clause(Clause,Head2,Body2), !,
 9480	Head1 = Head2, Body1 = Body2.
 9481
 9482hypothesis(Head1,Body1,Label):-
 9483	'$aleph_search'(pclause,pclause(Head2,Body2)), !,
 9484	Head1 = Head2, Body1 = Body2,
 9485	get_hyp_label((Head2:-Body2),Label).
 9486hypothesis(Head1,Body1,Label):-
 9487        '$aleph_global'(hypothesis,hypothesis(_,Theory,_,_)),
 9488	(Theory = [_|_] -> aleph_member(Clause,Theory);
 9489		Theory = Clause),
 9490	split_clause(Clause,Head2,Body2), 
 9491	Head1 = Head2, Body1 = Body2,
 9492	get_hyp_label((Head2:-Body2),Label).
 9493
 9494rdhyp:-
 9495	retractall('$aleph_search'(pclause,_)),
 9496	retractall('$aleph_search'(covers,_)),
 9497	retractall('$aleph_search'(coversn,_)),
 9498        read(Clause),
 9499        add_hyp(Clause),
 9500        nl,
 9501        show(hypothesis).
 9502
 9503addhyp:-
 9504	'$aleph_global'(hypothesis,hypothesis(Label,Theory,PCover,NCover)),
 9505	Theory = [_|_], !,
 9506	add_theory(Label,Theory,PCover,NCover).
 9507addhyp:-
 9508        '$aleph_global'(hypothesis,hypothesis(Label,_,PCover,_)), !,   
 9509        rm_seeds,
 9510        worse_coversets(PCover,pos,Label,Worse),
 9511        (Worse = [] -> true;
 9512        	'$aleph_global'(last_clause,last_clause(NewClause)),
 9513                update_coversets(Worse,NewClause,pos,Label)), !.
 9514addhyp:-
 9515        '$aleph_search'(selected,selected(Label,RClause,PCover,NCover)), !,
 9516        add_hyp(Label,RClause,PCover,NCover),
 9517        rm_seeds,
 9518        worse_coversets(PCover,pos,Label,Worse),
 9519        (Worse = [] -> true;
 9520        	'$aleph_global'(last_clause,last_clause(NewClause)),
 9521                update_coversets(Worse,NewClause,pos,Label)), !.
 9522
 9523% add bottom clause as hypothesis
 9524%	provided minacc, noise and search constraints are met
 9525%	otherwise the example saturated is added as hypothesis
 9526add_bottom:-
 9527	retractall('$aleph_search'(selected,selected(_,_,_,_))),
 9528	bottom(Bottom),
 9529	add_hyp(Bottom),
 9530        '$aleph_global'(hypothesis,hypothesis(Label,Clause,_,_)),
 9531	(clause_ok(Clause,Label) -> true;
 9532		'$aleph_sat'(example,example(Num,Type)),
 9533		example(Num,Type,Example),
 9534		retract('$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
 9535		setting(evalfn,Evalfn),
 9536		complete_label(Evalfn,Example,[1,0,1],Label1),
 9537		asserta('$aleph_global'(hypothesis,hypothesis(Label1,(Example:-true),[Num-Num],[])))).
 9538
 9539	
 9540% specialise a hypothesis by recursive construction of
 9541% abnormality predicates
 9542sphyp:-
 9543	retractall('$aleph_search'(sphyp,hypothesis(_,_,_,_))),
 9544	retractall('$aleph_search'(gcwshyp,hypothesis(_,_,_,_))),
 9545        retract('$aleph_global'(hypothesis,
 9546				hypothesis([P,N,L|T],Clause,PCover,NCover))),
 9547        asserta('$aleph_search'(sphyp,hypothesis([P,N,L|T],Clause,PCover,NCover))),
 9548        store(searchstate),
 9549        gcws,
 9550        retractall('$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
 9551        asserta('$aleph_global'(hypothesis,
 9552			hypothesis([P,N,L|T],Clause,PCover,NCover))),
 9553        reinstate(searchstate).
 9554
 9555addgcws:-
 9556        retract('$aleph_search'(gcwshyp,hypothesis(Label,C,P,N))), !,   
 9557	asserta('$aleph_search'(gcwshyp,hypothesis(Label,C,P,N))),
 9558	addhyp,
 9559	add_gcws.
 9560
 9561rmhyp:-
 9562        retract('$aleph_search'(pclause,pclause(Head,Body))),
 9563        asserta('$aleph_local'(pclause,pclause(Head,Body))), !.
 9564rmhyp:-
 9565        retract('$aleph_global'(hypothesis,hypothesis(Label,Clause1,P,N))),
 9566        asserta('$aleph_local'(hypothesis,hypothesis(Label,Clause1,P,N))), !.
 9567rmhyp.
 9568
 9569
 9570covers:-
 9571        get_hyp(Hypothesis),
 9572        label_create(Hypothesis,Label),
 9573        extract_cover(pos,Label,P),
 9574        examples(pos,P),
 9575	length(P,PC),
 9576	p1_message('examples covered'),
 9577	p_message(PC),
 9578	retractall('$aleph_search'(covers,_)),
 9579	asserta('$aleph_search'(covers,covers(P,PC))).
 9580coversn:-
 9581        get_hyp(Hypothesis),
 9582        label_create(Hypothesis,Label),
 9583        extract_cover(neg,Label,N),
 9584        examples(neg,N),
 9585	length(N,NC),
 9586	p1_message('examples covered'),
 9587	p_message(NC),
 9588	retractall('$aleph_search'(coversn,_)),
 9589	asserta('$aleph_search'(coversn,coversn(N,NC))).
 9590
 9591% covers(-Number)
 9592% 	as in covers/0, but first checks if being done
 9593% 	within a greedy search
 9594covers(P):-
 9595	get_hyp(Hypothesis),
 9596	(setting(greedy,true) -> 
 9597		'$aleph_global'(atoms,atoms_left(pos,Pos));
 9598		'$aleph_global'(atoms,atoms(pos,Pos))),
 9599	label_create(Hypothesis,pos,Pos,Label),
 9600	retractall('$aleph_search'(covers,_)),
 9601	extract_pos(Label,PCover),
 9602	interval_count(PCover,P),
 9603	asserta('$aleph_search'(covers,covers(PCover,P))).
 9604
 9605% coversn(-Number)
 9606% 	as in coversn/0, but first checks if being done
 9607% 	within a greedy search
 9608coversn(N):-
 9609	get_hyp(Hypothesis),
 9610	(setting(greedy,true) ->
 9611		'$aleph_global'(atoms_left,atoms_left(neg,Neg));
 9612		'$aleph_global'(atoms_left,atoms(neg,Neg))),
 9613	label_create(Hypothesis,neg,Neg,Label),
 9614	retractall('$aleph_search'(coversn,_)),
 9615	extract_neg(Label,NCover),
 9616	interval_count(NCover,N),
 9617	asserta('$aleph_search'(coversn,coverns(NCover,N))).
 9618
 9619% covers(-List,-Number)
 9620% 	as in covers/1, but returns list of examples covered and their count
 9621covers(PList,P):-
 9622	get_hyp(Hypothesis),
 9623	(setting(greedy,true) -> 
 9624		'$aleph_global'(atoms,atoms_left(pos,Pos));
 9625		'$aleph_global'(atoms,atoms(pos,Pos))),
 9626	label_create(Hypothesis,pos,Pos,Label),
 9627	retractall('$aleph_search'(covers,_)),
 9628	extract_pos(Label,PCover),
 9629	intervals_to_list(PCover,PList),
 9630	length(PList,P),
 9631	asserta('$aleph_search'(covers,covers(PCover,P))).
 9632
 9633% coversn(-List,-Number)
 9634% 	as in coversn/1, but returns list of examples covered and their count
 9635coversn(NList,N):-
 9636	get_hyp(Hypothesis),
 9637	(setting(greedy,true) ->
 9638		'$aleph_global'(atoms_left,atoms_left(neg,Neg));
 9639		'$aleph_global'(atoms_left,atoms(neg,Neg))),
 9640	label_create(Hypothesis,neg,Neg,Label),
 9641	retractall('$aleph_search'(coversn,_)),
 9642	extract_neg(Label,NCover),
 9643	intervals_to_list(NCover,NList),
 9644	length(NList,N),
 9645	asserta('$aleph_search'(coversn,coverns(NCover,N))).
 9646
 9647example_saturated(Example):-
 9648	'$aleph_sat'(example,example(Num,Type)),
 9649	example(Num,Type,Example).
 9650
 9651reset:-
 9652        clean_up,
 9653	clear_cache,
 9654	aleph_abolish('$aleph_global'/2),
 9655	aleph_abolish(example/3),
 9656	assert_static(example(0,uspec,false)),
 9657	set_default(_),
 9658	!.
 9659
 9660% Generic timing routine due to Mark Reid.
 9661% Under cygwin, cputime cannot be trusted
 9662% so walltime is used instead. To use cputime, set the body of this
 9663% predicate to "Time is cputime".
 9664stopwatch(Time) :-
 9665        Time is cputime.
 9666%       statistics(walltime,[Time|_]).
 9667
 9668wallclock(Time):-
 9669	statistics(real_time,[Time|_]).
 9670
 9671time(P,N,[Mean,Sd]):-
 9672        time_loop(N,P,Times),
 9673	mean(Times,Mean),
 9674	sd(Times,Sd).
 9675
 9676test(F,Flag,N,T):-
 9677	retractall('$aleph_local'(covered,_)),
 9678	retractall('$aleph_local'(total,_)),
 9679	asserta('$aleph_local'(covered,0)),
 9680	asserta('$aleph_local'(total,0)),
 9681	(F = [_|_] ->
 9682		test_files(F,Flag);
 9683		test_file(F,Flag)
 9684	),
 9685	retract('$aleph_local'(covered,N)),
 9686	retract('$aleph_local'(total,T)).
 9687
 9688test_files([],_).
 9689test_files([File|Files],Flag):-
 9690	test_file(File,Flag),
 9691	test_files(Files,Flag).
 9692
 9693test_file('?',_):- !.
 9694test_file(File,Flag):-
 9695	setting(portray_examples,Pretty),
 9696	aleph_open(File,read,Stream), !,
 9697	repeat,
 9698	read(Stream,Example),
 9699	(Example = end_of_file -> close(Stream);
 9700		retract('$aleph_local'(total,T0)),
 9701		T1 is T0 + 1,
 9702		asserta('$aleph_local'(total,T1)),
 9703		(once(depth_bound_call(Example)) ->
 9704			(Flag = show ->
 9705				p1_message(covered),
 9706				aleph_portray(Example,Pretty),
 9707				nl;
 9708				true);
 9709			(Flag = show ->
 9710				p1_message('not covered'),
 9711				aleph_portray(Example,Pretty),
 9712				nl;
 9713				true),
 9714			fail),
 9715		retract('$aleph_local'(covered,N0)),
 9716		N1 is N0 + 1,
 9717		asserta('$aleph_local'(covered,N1)),
 9718		fail),
 9719	!.
 9720test_file(File,_):-
 9721	p1_message('cannot open'), p_message(File).
 9722
 9723in(false,_):-
 9724	!,
 9725	fail.
 9726in(bottom,Lit):-
 9727	!,
 9728        '$aleph_sat'(lastlit,Last),
 9729        get_clause(1,Last,[],FlatClause),
 9730	aleph_member(Lit,FlatClause).
 9731in((Head:-true),Head):- !.
 9732in((Head:-Body),L):-
 9733	!,
 9734	in((Head,Body),L).
 9735in((L1,_),L1).
 9736in((_,R),L):-
 9737	!,
 9738	in(R,L).
 9739in(L,L).
 9740
 9741in((L1,L),L1,L).
 9742in((L1,L),L2,(L1,Rest)):-
 9743	!,
 9744	in(L,L2,Rest).
 9745in(L,L,true).
 9746
 9747% draw a random number from a distribution
 9748random(X,normal(Mean,Sigma)):-
 9749	var(X), !,
 9750	normal(Mean,Sigma,X).
 9751random(X,normal(_,_)):-
 9752	!,
 9753	number(X).
 9754	% X >= Mean - 3*Sigma,
 9755	% X =< Mean + 3*Sigma.
 9756random(X,Distr):-
 9757	Distr = [_|_],
 9758	var(X), !,
 9759        draw_element(Distr,X1),
 9760	X = X1.
 9761random(X,Distr):-
 9762	Distr = [_|_],
 9763	nonvar(X), !,
 9764        aleph_member(Prob-X,Distr), 
 9765	Prob > 0.0.
 9766
 9767mean(L,M):-
 9768	sum(L,Sum),
 9769	length(L,N),
 9770	M is Sum/N.
 9771
 9772sd(L,Sd):-
 9773	length(L,N),
 9774	(N = 1 -> Sd = 0.0;
 9775		sum(L,Sum),
 9776		sumsq(L,SumSq),
 9777		Sd is sqrt(SumSq/(N-1) - (Sum*Sum)/(N*(N-1)))).
 9778
 9779sum([],0).
 9780sum([X|T],S):-
 9781	sum(T,S1),
 9782	S is X + S1.
 9783
 9784sumsq([],0).
 9785sumsq([X|T],S):-
 9786	sumsq(T,S1),
 9787	S is X*X + S1.
 9788
 9789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 9790% 
 9791% auxilliary definitions  for some of the above
 9792
 9793set_default(A):-
 9794	default_setting(A,B),
 9795	set(A,B),
 9796	fail.
 9797set_default(_).
 9798
 9799default_setting(A,B):-
 9800	set_def(A,_,_,_,B,_),
 9801	B \= ''.
 9802
 9803% special case for threads as only SWI supports it
 9804check_setting(threads,B):-
 9805	set_def(threads,_,_,Dom,_,_),
 9806	check_legal(Dom,B), 
 9807	prolog_type(P),
 9808	(B > 1 ->
 9809		(P = swi -> true;
 9810                	err_message(set(threads,B)),
 9811                	fail
 9812		);
 9813		true
 9814	), !.
 9815check_setting(A,B):-
 9816	set_def(A,_,_,Dom,_,_), !,
 9817	(check_legal(Dom,B) -> true;
 9818		err_message(set(A,B))).
 9819check_setting(_,_).
 9820
 9821check_legal(int(L)-int(U),X):-
 9822	!,
 9823	number(L,IL),
 9824	number(U,IU),
 9825	number(X,IX),
 9826	IX >= IL,
 9827	IX =< IU.
 9828check_legal(float(L)-float(U),X):-
 9829	!,
 9830	number(L,FL),
 9831	number(U,FU),
 9832	number(X,FX),
 9833	FX >= FL,
 9834	FX =< FU.
 9835check_legal([H|T],X):-
 9836	!,
 9837	aleph_member1(X,[H|T]).
 9838check_legal(read(filename),X):-
 9839	X \= '?',
 9840	!,
 9841	exists(X).
 9842check_legal(_,_).
 9843
 9844number(+inf,Inf):-
 9845	Inf is inf, !.
 9846number(-inf,MInf):-
 9847	MInf is -inf, !.
 9848number(X,Y):-
 9849	Y is X, !.
 9850
 9851setting_definition(A,B,C,D,E,F1):-
 9852	set_def(A,B,C,D,E,F),
 9853	(F = noshow -> F1 = dontshow; F = F1).
 9854
 9855% set_def(Parameter,Class,TextDescr,Type,Default,Flag)
 9856set_def(abduce, search-search_strategy,
 9857	'Abduce Atoms and Generalise',
 9858	[true, false], false,
 9859	show).
 9860set_def(best, search-search_space,
 9861	'Label to beat',
 9862	prolog_term,'',
 9863	show).
 9864set_def(cache_clauselength, miscellaneous,
 9865	'Maximum Length of Cached Clauses',
 9866	int(1)-int(+inf), 3,
 9867	show).
 9868set_def(caching, miscellaneous,
 9869	'Cache Clauses in Search',
 9870	[true, false], false,
 9871	show).
 9872set_def(check_redundant, miscellaneous,
 9873	'Check for Redundant Literals',
 9874	[true, false], false,
 9875	show).
 9876set_def(check_good, miscellaneous,
 9877	'Check good clauses for duplicates',
 9878	[true, false], false,
 9879	show).
 9880set_def(check_useless, saturation,
 9881	'Remove I/O unconnected Literals',
 9882	[true, false], false,
 9883	show).
 9884set_def(classes, tree,
 9885	'Class labels',
 9886	prolog_term,'',
 9887	show).
 9888set_def(clauselength_distribution, search-search_strategy,
 9889	'Probablity Distribution over Clauses',
 9890	prolog_term,'',
 9891	show).
 9892set_def(clauselength, search-search_space,
 9893	'Maximum Clause Length',
 9894	int(1)-int(+inf), 4,
 9895	show).
 9896set_def(clauses, search-search_space,
 9897	'Maximum Clauses per Theory',
 9898	int(1)-int(+inf),'',
 9899	show).
 9900set_def(condition, evaluation,
 9901	'Condition SLP',
 9902	[true, false], false,
 9903	show).
 9904set_def(confidence, tree,
 9905	'Confidence for Rule Pruning',
 9906	float(0.0)-float(1.0), 0.95,
 9907	show).
 9908set_def(construct_bottom, saturation,
 9909	'Build a bottom clause',
 9910	[saturation, reduction, false], saturation,
 9911	show).
 9912set_def(depth, miscellaneous,
 9913	'Theorem Proving Depth',
 9914	int(1)-int(+inf), 10,
 9915	show).
 9916set_def(evalfn, evaluation,
 9917	'Evaluation Function',
 9918	[coverage, compression, posonly, pbayes, accuracy, laplace,
 9919	auto_m, mestimate, mse, entropy, gini, sd, wracc, user], coverage,
 9920	show).
 9921set_def(explore, search-search_space,
 9922	'Exhaustive Search of all alternatives',
 9923	[true, false], false,
 9924	show).
 9925set_def(good, miscellaneous,
 9926	'Store good clauses',
 9927	[true, false], false,
 9928	show).
 9929set_def(goodfile, miscellaneous,
 9930	'File of good clauses',
 9931	write(filename),'',
 9932	show).
 9933set_def(gsamplesize, evaluation,
 9934	'Size of random sample',
 9935	int(1)-int(+inf), 100,
 9936	show).
 9937set_def(i, saturation,
 9938	'bound layers of new variables',
 9939	int(1)-int(+inf), 2,
 9940	show).
 9941set_def(interactive, search-search_strategy,
 9942	'Interactive theory construction',
 9943	[true, false], false,
 9944	show).
 9945set_def(language, search-search_space,
 9946	'Maximum occurrence of any predicate symbol in a clause',
 9947	int(1)-int(+inf), +inf,
 9948	show).
 9949set_def(lazy_negs, evaluation,
 9950	'Lazy theorem proving on negative examples',
 9951	[true, false], false,
 9952	show).
 9953set_def(lazy_on_contradiction, evaluation,
 9954	'Lazy theorem proving on contradictions',
 9955	[true, false], false,
 9956	show).
 9957set_def(lazy_on_cost, evaluation,
 9958	'Lazy theorem proving on cost',
 9959	[true, false], false,
 9960	show).
 9961set_def(lookahead, search-search_space,
 9962	'Lookahead for automatic refinement operator',
 9963	int(1)-int(+inf), 1,
 9964	show).
 9965set_def(m, evaluation,
 9966	'M-estimate',
 9967	float(0.0)-float(+inf),'',
 9968	show).
 9969set_def(max_abducibles, search-search_space,
 9970	'Maximum number of atoms in an abductive explanation',
 9971	int(1)-int(+inf), 2,
 9972	show).
 9973set_def(max_features, miscellaneous,
 9974	'Maximum number of features to be constructed',
 9975	int(1)-int(+inf), +inf,
 9976	show).
 9977set_def(minacc, evaluation,
 9978	'Minimum clause accuracy',
 9979	float(0.0)-float(1.0), 0.0,
 9980	show).
 9981set_def(mingain, tree,
 9982	'Minimum expected gain',
 9983	float(0.000001)-float(+inf), 0.05,
 9984	show).
 9985set_def(minpos, evaluation,
 9986	'Minimum pos covered by a clause',
 9987	int(0)-int(+inf), 1,
 9988	show).
 9989set_def(minposfrac, evaluation,
 9990	'Minimum proportion of positives covered by a clause',
 9991	float(0.0)-float(1.0), 0,
 9992	show).
 9993set_def(minscore, evaluation,
 9994	'Minimum utility of an acceptable clause',
 9995	float(-inf)-float(+inf), -inf,
 9996	show).
 9997set_def(moves, search-search_strategy,
 9998	'Number of moves in a randomised local search',
 9999	int(0)-int(+inf), 5,
10000	show).
10001set_def(newvars, search-search_space,
10002	'Existential variables in a clause',
10003	int(0)-int(+inf), +inf,
10004	show).
10005set_def(nodes, search-search_space,
10006	'Nodes to be explored in the search',
10007	int(1)-int(+inf), 5000,
10008	show).
10009set_def(noise, evaluation,
10010	'Maximum negatives covered',
10011	int(0)-int(+inf), 0,
10012	show).
10013set_def(nreduce_bottom, saturation,
10014	'Negative examples based reduction of bottom clause',
10015	[true, false], false,
10016	show).
10017set_def(openlist, search-search_space,
10018	'Beam width in a greedy search',
10019	int(1)-int(+inf), +inf,
10020	show).
10021set_def(optimise_clauses, miscellaneous,
10022	'Perform query Optimisation',
10023	[true, false], false,
10024	show).
10025set_def(permute_bottom, saturation,
10026	'Randomly permute order of negative literals in the bottom clause',
10027	[true, false], false,
10028	show).
10029set_def(portray_examples, miscellaneous,
10030	'Pretty print examples',
10031	[true, false], false,
10032	show).
10033set_def(portray_hypothesis, miscellaneous,
10034	'Pretty print hypotheses',
10035	[true, false], false,
10036	show).
10037set_def(portray_literals, miscellaneous,
10038	'Pretty print literals',
10039	[true, false], false,
10040	show).
10041set_def(portray_search, miscellaneous,
10042	'Pretty print search',
10043	[true, false], false,
10044	show).
10045set_def(print, miscellaneous,
10046	'Literals printed per line',
10047	int(1)-int(+inf), 4,
10048	show).
10049set_def(prior, miscellaneous,
10050	'Prior class distribution',
10051	prolog_term,'',
10052	show-ro).
10053set_def(proof_strategy, miscellaneous,
10054	'Current proof strategy',
10055	[restricted_sld, sld, user], restricted_sld,
10056	show).
10057set_def(prooftime, miscellaneous,
10058	'Theorem proving time',
10059	float(0.0)-float(+inf), +inf,
10060	show).
10061set_def(prune_tree, tree,
10062	'Tree pruning',
10063	[true, false], false,
10064	show).
10065set_def(recordfile, miscellaneous,
10066	'Log filename',
10067	write(filename),'',
10068	show).
10069set_def(record, miscellaneous,
10070	'Log to file',
10071	[true, false], false,
10072	show).
10073set_def(refineop, search-search_strategy,
10074	'Current refinement operator',
10075	[user, auto, scs, false],'',
10076	show-ro).
10077set_def(refine, search-search_strategy,
10078	'Nature of customised refinement operator',
10079	[user, auto, scs, false], false,
10080	show).
10081set_def(resample, search-search_strategy,
10082	'Number of times to resample an example',
10083	int(1)-int(+inf), 1,
10084	show).
10085set_def(rls_type, search-search_strategy,
10086	'Type of randomised local search',
10087	[gsat, wsat, rrr, anneal], gsat,
10088	show).
10089set_def(rulefile, miscellaneous,
10090	'Rule file',
10091	write(filename),'',
10092	show).
10093set_def(samplesize, search-search_strategy,
10094	'Size of sample',
10095	int(0)-int(+inf), 0,
10096	show).
10097set_def(scs_percentile, search-search_strategy,
10098	'Percentile of good clauses for SCS search',
10099	float(0.0)-float(100.0),'',
10100	show).
10101set_def(scs_prob, search-search_strategy,
10102	'Probability of getting a good clause in SCS search',
10103	float(0.0)-float(1.0),'',
10104	show).
10105set_def(scs_sample, search-search_strategy,
10106	'Sample size in SCS search',
10107	int(1)-int(+inf), '',
10108	show).
10109set_def(search, search-search_strategy,
10110	'Search Strategy',
10111	[bf, df, heuristic, ibs, ils, rls, scs, id, ic, ar, false], bf,
10112	show).
10113set_def(searchstrat, search-search_strategy,
10114	'Current Search Strategy',
10115	[bf, df, heuristic, ibs, ils, rls, scs, id, ic, ar], bf,
10116	show-ro).
10117set_def(searchtime, search-search_strategy,
10118	'Search time in seconds',
10119	float(0.0)-float(+inf), +inf,
10120	show).
10121set_def(skolemvars, miscellaneous,
10122	'Counter for non-ground examples',
10123	int(1)-int(+inf), 10000,
10124	show).
10125set_def(splitvars, saturation,
10126	'Split variable co-refencing',
10127	[true, false], false,
10128	show).
10129set_def(stage, miscellaneous,
10130	'Aleph processing mode',
10131	[saturation, reduction, command], command,
10132	show-ro).
10133set_def(store_bottom, saturation,
10134	'Store bottom',
10135	[true, false], false,
10136	show).
10137set_def(subsample, search-search_strategy,
10138	'Subsample for evaluating a clause',
10139	[true,false], false,
10140	show).
10141set_def(subsamplesize, search-search_strategy,
10142	'Size of subsample for evaluating a clause',
10143	int(1)-int(+inf), +inf,
10144	show).
10145set_def(temperature, search-search_strategy,
10146	'Temperature for randomised search annealing',
10147	float(0.0)-float(+inf), '',
10148	show).
10149set_def(test_neg, miscellaneous,
10150	'Negative examples for testing theory',
10151	read(filename),'',
10152	show).
10153set_def(test_pos, miscellaneous,
10154	'Positive examples for testing theory',
10155	read(filename),'',
10156	show).
10157set_def(threads, miscellaneous,
10158	'Number of threads',
10159	int(1)-int(+inf), 1,
10160        show).
10161set_def(train_neg, miscellaneous,
10162	'Negative examples for training',
10163	read(filename),'',
10164	show).
10165set_def(train_pos, miscellaneous,
10166	'Positive examples for training',
10167	read(filename),'',
10168	show).
10169set_def(tree_type, tree,
10170	'Type of tree to construct',
10171	[classification, class_probability, regression, model], '',
10172	show).
10173set_def(tries, search-search_strategy,
10174	'Number of restarts for a randomised search',
10175	int(1)-int(+inf), 10,
10176	show).
10177set_def(typeoverlap, miscellaneous,
10178	'Type overlap for induce_modes',
10179	float(0.0)-float(1.0), 0.95,
10180	show).
10181set_def(uniform_sample, search-search_strategy,
10182	'Distribution to draw clauses from randomly',
10183	[true, false], false,
10184	show).
10185set_def(updateback, miscellaneous,
10186	'Update background knowledge with clauses found on search',
10187	[true, false], true,
10188	noshow).
10189set_def(verbosity, miscellaneous,
10190	'Level of verbosity',
10191	int(1)-int(+inf), 1,
10192	show).
10193set_def(version, miscellaneous,
10194	'Aleph version',
10195	int(0)-int(+inf), 5,
10196	show-ro).
10197set_def(walk, search-search_strategy,
10198	'Random walk probability for Walksat',
10199	float(0.0)-float(1.0), '',
10200	show).
10201
10202
10203% the following needed for compatibility with P-Progol
10204special_consideration(search,ida):-
10205	set(search,bf), set(evalfn,coverage), !.
10206special_consideration(search,compression):-
10207	set(search,heuristic), set(evalfn,compression), !.
10208special_consideration(search,posonly):-
10209	set(search,heuristic), set(evalfn,posonly), !.
10210special_consideration(search,user):-
10211	set(search,heuristic), set(evalfn,user), !.
10212
10213special_consideration(refine,Refine):-
10214	set(refineop,Refine), !.
10215special_consideration(refineop,auto):-
10216	gen_auto_refine, !.
10217
10218special_consideration(portray_literals,true):-
10219	set(print,1), !.
10220
10221special_consideration(record,true):-
10222	noset(recordfile_stream),
10223	(setting(recordfile,F) -> 
10224		aleph_open(F,append,Stream),
10225		set(recordfile_stream,Stream);
10226		true), !.
10227special_consideration(record,false):-
10228	noset(recordfile_stream), !.
10229special_consideration(recordfile,File):-
10230	noset(recordfile_stream), 
10231	(setting(record,true) -> 
10232		aleph_open(File,append,Stream),
10233		set(recordfile_stream,Stream);
10234		true), !.
10235special_consideration(good,true):-
10236	noset(goodfile_stream),
10237	(setting(goodfile,F) -> 
10238		aleph_open(F,append,Stream),
10239		set(goodfile_stream,Stream);
10240		true), !.
10241special_consideration(good,false):-
10242	noset(goodfile_stream), !.
10243special_consideration(goodfile,File):-
10244	noset(goodfile_stream), 
10245	(setting(good,true) -> 
10246		aleph_open(File,append,Stream),
10247		set(goodfile_stream,Stream);
10248		true), !.
10249special_consideration(minscore,_):-
10250	aleph_abolish('$aleph_feature'/2), !.
10251special_consideration(_,_).
10252
10253rm_special_consideration(portray_literals,_):-
10254	set_default(print), !.
10255rm_special_consideration(refine,_):-
10256	set_default(refineop), !.
10257rm_special_consideration(record,_):-
10258	noset(recordfile_stream), !.
10259rm_special_consideration(recordfile_stream,_):-
10260	(setting(recordfile_stream,S) -> close(S); true), !.
10261rm_special_consideration(good,_):-
10262	noset(goodfile_stream), !.
10263rm_special_consideration(goodfile_stream,_):-
10264	(setting(goodfile_stream,S) -> close(S); true), !.
10265rm_special_consideration(_,_).
10266
10267
10268get_hyp((Head:-Body)):-
10269	'$aleph_search'(pclause,pclause(Head,Body)), !.
10270get_hyp(Hypothesis):-
10271        '$aleph_global'(hypothesis,hypothesis(_,Hypothesis,_,_)).
10272
10273add_hyp(end_of_file):- !.
10274add_hyp(Clause):-
10275        nlits(Clause,L),
10276	label_create(Clause,Label),
10277        extract_count(pos,Label,PCount),
10278        extract_count(neg,Label,NCount),
10279        retractall('$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
10280        extract_pos(Label,P),
10281        extract_neg(Label,N),
10282	setting(evalfn,Evalfn),
10283	complete_label(Evalfn,Clause,[PCount,NCount,L],Label1),
10284        asserta('$aleph_global'(hypothesis,hypothesis(Label1,Clause,P,N))).
10285
10286add_hyp(Label,Clause,P,N):-
10287        retractall('$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
10288        asserta('$aleph_global'(hypothesis,hypothesis(Label,Clause,P,N))).
10289
10290add_theory(Label,Theory,PCover,NCover):-
10291        aleph_member(C,Theory),
10292	add_hyp(Label,C,PCover,NCover),
10293	update_theory(_),
10294        fail.
10295add_theory(_,_,PCover,NCover):-
10296	rm_seeds(pos,PCover),
10297	(setting(evalfn,posonly) -> rm_seeds(rand,NCover); true),
10298	'$aleph_global'(atoms_left,atoms_left(pos,PLeft)),
10299	interval_count(PLeft,PL),
10300	p1_message('atoms left'), p_message(PL), !.
10301
10302add_gcws:-
10303	retract('$aleph_search'(gcwshyp,hypothesis(L,C,P,N))),
10304	asserta('$aleph_global'(hypothesis,hypothesis(L,C,P,N))),
10305	update_theory(_),
10306	fail.
10307add_gcws.
10308
10309
10310restorehyp:-
10311	retract('$aleph_local'(pclause,pclause(Head,Body))),
10312	assertz('$aleph_search'(pclause,pclause(Head,Body))), !.
10313restorehyp:-
10314	retract('$aleph_local'(hypothesis,hypothesis(Label,Clause1,P,N))),
10315        asserta('$aleph_global'(hypothesis,hypothesis(Label,Clause1,P,N))), !.
10316restorehyp.
10317
10318get_hyp_label(_,Label):- var(Label), !.
10319get_hyp_label((_:-Body),[P,N,L]):-
10320        nlits(Body,L1),
10321        L is L1 + 1,
10322        ('$aleph_search'(covers,covers(_,P))-> true;
10323                        covers(_),
10324                        '$aleph_search'(covers,covers(_,P))),
10325        ('$aleph_search'(coversn,coverns(_,N))-> true;
10326                        coversn(_),
10327                        '$aleph_search'(coversn,coversn(_,N))).
10328 
10329
10330show_global(Key,Pred):-
10331        '$aleph_global'(Key,Pred),
10332        copy_term(Pred,Pred1), numbervars(Pred1,0,_),
10333        aleph_writeq(Pred1), write('.'), nl,
10334        fail.
10335show_global(_,_).
10336
10337aleph_portray(hypothesis,true):-
10338	aleph_portray(hypothesis), !.
10339aleph_portray(hypothesis,false):- 
10340	p_message('hypothesis'),
10341	hypothesis(Head,Body,_),
10342	pp_dclause((Head:-Body)), !.
10343aleph_portray(_,hypothesis):-  !.
10344
10345aleph_portray(search,true):-
10346	aleph_portray(search), !.
10347aleph_portray(search,_):- !.
10348
10349aleph_portray(train_pos,true):-
10350	aleph_portray(train_pos), !.
10351aleph_portray(train_pos,_):-
10352	!,
10353	setting(train_pos,File),
10354	show_file(File).
10355
10356aleph_portray(train_neg,true):-
10357	aleph_portray(train_neg), !.
10358aleph_portray(train_neg,_):-
10359	!,
10360	setting(train_neg,File),
10361	show_file(File).
10362
10363aleph_portray(test_pos,true):-
10364	aleph_portray(test_pos), !.
10365aleph_portray(test_pos,_):-
10366	!,
10367	setting(test_pos,File),
10368	show_file(File).
10369
10370aleph_portray(test_neg,true):-
10371	aleph_portray(test_neg), !.
10372aleph_portray(test_neg,_):-
10373	!,
10374	setting(test_neg,File),
10375	show_file(File).
10376
10377aleph_portray(Lit,true):-
10378	aleph_portray(Lit), !.
10379aleph_portray(Lit,_):-
10380        aleph_writeq(Lit).
10381
10382aleph_writeq(Lit):-
10383	write_term(Lit,[numbervars(true),quoted(true)]).
10384
10385show_file(File):-
10386	aleph_open(File,read,Stream), 
10387	repeat,
10388	read(Stream,Clause),
10389	(Clause = end_of_file -> close(Stream);
10390		writeq(Clause), write('.'), nl,
10391		fail).
10392
10393time_loop(0,_,[]):- !.
10394time_loop(N,P,[T|Times]):-
10395	wallclock(S),
10396        P,
10397	wallclock(F),
10398	T is F - S,
10399        N1 is N - 1,
10400        time_loop(N1,P,Times).
10401
10402list_profile :-
10403        % get number of calls for each profiled procedure
10404        findall(D-P,profile_data(P,calls,D),LP),
10405        % sort them
10406        sort(LP,SLP),
10407        % and output (note the most often called predicates will come last
10408        write_profile_data(SLP).
10409
10410write_profile_data([]).
10411        write_profile_data([D-P|SLP]) :-
10412        % just swap the two calls to get most often called predicates first.
10413        format('~w: ~w~n', [P,D]),
10414        write_profile_data(SLP).
10415 
10416
10417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10418% F I N A L  C O M M A N D S
10419
10420:-
10421	nl, nl,
10422	write('A L E P H'), nl,
10423	aleph_version(Version), write('Version '), write(Version), nl,
10424	aleph_version_date(Date), write('Last modified: '), write(Date), nl, nl,
10425	aleph_manual(Man),
10426	write('Manual: '),
10427	write(Man), nl, nl.10428
10429:- aleph_version(V), set(version,V), reset.