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:- module(aleph,
   34	  [ 
   35		induce/1,
   36		induce_tree/1,
   37		induce_max/1,
   38		induce_cover/1,
   39		induce_incremental/1,
   40		induce_clauses/1,
   41		induce_theory/1,
   42		induce_modes/1,
   43		induce_features/1,
   44		induce_constraints/1,
   45		sat/1,
   46		aleph_set/2,
   47		aleph_setting/2,
   48		goals_to_list/2,
   49                clause_to_list/2,
   50                aleph_subsumes/2,
   51		aleph_delete/3,
   52		hypothesis/3,
   53		hypothesis/4,
   54		var_types/3,
   55		show/1,
   56		rdhyp/1,
   57		addhyp_i/1,
   58		sphyp_i/1,
   59		covers/1,
   60		coversn/1,
   61		reduce/1,
   62		abducible/1,
   63		bottom/1,
   64		commutative/1,
   65		man/1,
   66		symmetric/1,
   67		lazy_evaluate/1,
   68		model/1,
   69		positive_only/1,
   70		example_saturated/1,
   71		addgcws_i/1,
   72		rmhyp_i/1,
   73		random/2,
   74		aleph_random/1,
   75		mode/2,		modeh/2,		modeb/2,		good_clauses/1,		op(500,fy,#),		op(500,fy,*),		op(900,xfy,because)	  ]).

aleph

A Learning Engine for Proposing Hypotheses - ALEPH

Version 5

Aleph is an Inductive Logic Programming system developed by Ashwin Srinivasan:

http://www.cs.ox.ac.uk/activities/machlearn/Aleph/

Aleph v.5 was ported to SWI-Prolog by Fabrizio Riguzzi and Paolo Niccolò Giubelli.

Aleph is freely available for academic purposes. % If you intend to use it for commercial purposes then % please contact Ashwin Srinivasan first. %

author
- Ashwin Srinivasan, Fabrizio Riguzzi and Paolo Niccolò Giubelli.
  105:- use_module(library(arithmetic)). 
  106:-use_module(library(broadcast)).  107:-use_module(library(time)).  108:- arithmetic_function(inf/0).  109inf(1e10).
  110:-set_prolog_flag(unknown,warning).  111:- dynamic aleph_input_mod/1.  112
  113:- meta_predicate induce(:).  114:- meta_predicate induce_tree(:).  115:- meta_predicate induce_max(:).  116:- meta_predicate induce_cover(:).  117:- meta_predicate induce_incremental(:).  118:- meta_predicate induce_clauses(:).  119:- meta_predicate induce_theory(:).  120:- meta_predicate induce_modes(:).  121:- meta_predicate induce_features(:).  122:- meta_predicate induce_constraints(:).  123:- meta_predicate sat(:).  124:- meta_predicate aleph_set(:,+).  125:- meta_predicate aleph_setting(:,+).  126:- meta_predicate noset(:).  127:- meta_predicate model(:).  128:- meta_predicate mode(:,+).  129:- meta_predicate modeh(:,+).  130:- meta_predicate modeb(:,+).  131:- meta_predicate show(:).  132:- meta_predicate hypothesis(:,+,-).  133:- meta_predicate rdhyp(:).  134:- meta_predicate addhyp_i(:).  135:- meta_predicate sphyp_i(:).  136:- meta_predicate covers(:).  137:- meta_predicate coversn(:).  138:- meta_predicate reduce(:).  139:- meta_predicate abducible(:).  140:- meta_predicate bottom(:).  141:- meta_predicate commutative(:).  142:- meta_predicate symmetric(:).  143:- meta_predicate lazy_evaluate(:).  144:- meta_predicate positive_only(:).  145:- meta_predicate example_saturated(:).  146
  147
  148
  149:- meta_predicate addgcws_i(:).  150:- meta_predicate rmhyp_i(:).  151:- meta_predicate good_clauses(:).  152
  153
  154/* INIT ALEPH */
  155
  156system:term_expansion((:- aleph), []) :-
  157  prolog_load_context(module, M),
  158  assert(aleph_input_mod(M)),!,
  159  initialize(M).
  160
  161initialize(M):-
  162	% nl, nl,
  163	% write('A L E P H'), nl,
  164	% aleph:aleph_version(Version), write('Version '), write(Version), nl,
  165	% aleph:aleph_version_date(Date), write('Last modified: '), write(Date), nl, nl,
  166	% aleph:aleph_manual(Man),
  167	% write('Manual: '),
  168	% write(Man), nl, nl,
  169	aleph:aleph_version(V), aleph:set(version,V,M), aleph:reset(M),
  170  %findall(local_setting(P,V),default_setting_sc(P,V),L),
  171  %assert_all(L,M,_),
  172	M:dynamic((pos_on/0,neg_on/0,bg_on/0,incneg/1,incpos/1,in/1,bgc/1,bg/1)),
  173	 M:dynamic(('$aleph_feature'/2,
  174 '$aleph_global'/2,
  175 '$aleph_good'/3,
  176 '$aleph_local'/2,
  177 '$aleph_sat'/2,
  178 '$aleph_sat_atom'/2,
  179 '$aleph_sat_ovars'/2,
  180 '$aleph_sat_ivars'/2,
  181 '$aleph_sat_varsequiv'/2,
  182 '$aleph_sat_varscopy'/3,
  183 '$aleph_sat_terms'/4,
  184 '$aleph_sat_vars'/4,
  185 '$aleph_sat_litinfo'/6,
  186 '$aleph_search_cache'/1,
  187 '$aleph_search_prunecache'/1,
  188 '$aleph_search'/2,
  189 '$aleph_search_seen'/2,
  190 '$aleph_search_expansion'/4,
  191 '$aleph_search_gain'/4,
  192 '$aleph_search_node'/8,
  193 '$aleph_link_vars'/2,
  194 '$aleph_has_vars'/3,
  195 '$aleph_has_ovar'/4,
  196 '$aleph_has_ivar'/4,
  197 '$aleph_determination'/2,
  198 '$aleph_search_seen'/2)),
  199  M:dynamic((prune/1,cost/3,example/3,aleph_portray/1)),
  200  style_check(-discontiguous),
  201  aleph:init(swi,M),
  202  assert(M:(reduce:-reduce(_))),
  203  assert(M:(induce_constraints:-induce_constraints(_))),
  204  assert(M:(induce_modes:-induce_modes(_))),
  205  assert(M:(induce_incremental:-induce_incremental(_))),
  206  assert(M:(induce_clauses:-induce_clauses(_))),
  207  assert(M:(induce:-induce(_))),
  208  assert(M:(induce_tree:-induce_tree(_))),
  209  assert(M:(induce_max:-induce_max(_))),
  210  assert(M:(induce_cover:-induce_cover(_))),
  211  assert(M:(induce_theory:-induce_theory(_))),
  212  assert(M:(induce_features:-induce_features(_))),
  213  assert(M:(rdhyp:-rdhyp(_))),
  214  assert(M:(sphyp:-sphyp_i(_))),
  215  assert(M:(addgcws:-addgcws_i(_))),
  216  assert(M:(rmhyp:-rmhyp_i(_))),
  217  assert(M:(addhyp:-addhyp_i(_))),
  218  assert(M:(covers:-covers(_))),
  219  assert(M:(coversn:-coversn(_))),
  220
  221  aleph:clean_up(M),
  222  retractall(M:example(_,_,_)),
  223  aleph:reset(M).
  224
  225
  226system:term_expansion((:- begin_bg), []) :-
  227  prolog_load_context(module, M),
  228  aleph_input_mod(M),!,
  229  assert(M:bg_on).
  230
  231system:term_expansion(C, C) :-
  232  C\= (:- end_bg),
  233  prolog_load_context(module, M),	
  234  aleph_input_mod(M),
  235  M:bg_on,!.
  236
  237system:term_expansion((:- end_bg), []) :-
  238  prolog_load_context(module, M),
  239  aleph_input_mod(M),!,
  240  retractall(M:bg_on).
  241  %findall(C,M:bgc(C),L),
  242  %retractall(M:bgc(_)),
  243 % (M:bg(BG0)->
  244 %   retract(M:bg(BG0)),
  245 %   append(BG0,L,BG),
  246 %   assert(M:bg(BG))
  247 % ;
  248 %   assert_all(L,M,_)
  249 % ).
  250system:term_expansion((:- begin_in_pos), []) :-
  251  prolog_load_context(module, M),
  252  aleph_input_mod(M),!,
  253  assert(M:pos_on),
  254  clean_up_examples(pos,M),
  255	asserta(M:'$aleph_global'(size,size(pos,0))).
  256	
  257
  258system:term_expansion(C, []) :-	
  259  C\= (:- end_in_pos),
  260  prolog_load_context(module, M),
  261  aleph_input_mod(M),
  262  M:pos_on,!,aleph:record_example(nocheck,pos,C,_,M).
  263
  264system:term_expansion((:- end_in_pos), []) :-
  265  prolog_load_context(module, M),
  266  aleph_input_mod(M),!,
  267  retractall(M:pos_on).
  268  %findall(C,M:incpos(C),L),
  269  %retractall(M:incpos(_)),
  270%  (M:in(IN0)->
  271%    retract(M:in(IN0)),%
  272%	
  273%    append(IN0,L,IN),
  274%    assert(M:in(IN))
  275%  ;
  276%    assert(M:in(L))
  277%  ).
  278
  279%%%%%%
  280
  281system:term_expansion((:- begin_in_neg), []) :-
  282  prolog_load_context(module, M),
  283  aleph_input_mod(M),!,
  284  assert(M:neg_on),
  285	aleph:clean_up_examples(neg,M),
  286	asserta(M:'$aleph_global'(size,size(neg,0))).
  287
  288system:term_expansion(C, []) :-
  289  C\= (:- end_in_neg),
  290  prolog_load_context(module, M),
  291  aleph_input_mod(M),
  292  M:neg_on,!,aleph:record_example(nocheck,neg,C,_,M).
  293
  294system:term_expansion(:- mode(A,B), []) :-
  295  prolog_load_context(module, M),
  296  aleph_input_mod(M),!,
  297  aleph:mode(A,B,M).
  298
  299system:term_expansion(:- modeh(A,B), []) :-
  300  prolog_load_context(module, M),
  301  aleph_input_mod(M),!,
  302  aleph:modeh(A,B,M).
  303
  304system:term_expansion(:- modeb(A,B), []) :-
  305  prolog_load_context(module, M),
  306  aleph_input_mod(M),!,
  307  aleph:modeb(A,B,M).
  308
  309system:term_expansion(:- aleph_set(A,B), []) :-
  310  prolog_load_context(module, M),
  311  aleph_input_mod(M),!,
  312  aleph:set(A,B,M).
  313
  314system:term_expansion(:- determination(A,B), []) :-
  315  prolog_load_context(module, M),
  316  aleph_input_mod(M),!,
  317  aleph:determination(A,B,M).
  318
  319system:term_expansion((:- end_in_neg), []) :-
  320  prolog_load_context(module, M),
  321  aleph_input_mod(M),!,
  322  retractall(M:neg_on).
  323  %findall(C,M:incneg(C),L),
  324  %retractall(M:incneg(_)),
  325%
  326%  (M:in(IN0)->
  327%    retract(M:in(IN0)),
  328	
  329%    append(IN0,L,IN),
  330%    assert(M:in(IN))
  331%  ;
  332%    assert(M:in(L))
  333%  ).
  334 system:term_expansion((:- aleph_read_all), []) :-
  335        prolog_load_context(module, M),
  336 	aleph_input_mod(M),!.
  337
  338system:term_expansion(end_of_file, end_of_file) :-
  339  prolog_load_context(module, M),
  340  aleph_input_mod(M),!,
  341  retractall(pita_input_mod(M)),
  342  	aleph:record_targetpred(M), 	
  343	aleph:check_recursive_calls(M),
  344	aleph:check_prune_defs(M),
  345	aleph:check_user_search(M),
  346	aleph:check_posonly(M),
  347	aleph:check_auto_refine(M),
  348	aleph:check_abducibles(M),	
  349	%Aggiunti alla fine
  350	aleph:reset_counts(M),
  351	asserta(M:'$aleph_global'(last_clause,last_clause(0))),
  352	broadcast(examples(loaded)),
  353	(M:'$aleph_global'(size,size(pos,NP))-> true;NP=0),
  354	(NP > 0 -> ExP = [1-NP]; ExP = []),
  355	asserta(M:'$aleph_global'(atoms,atoms(pos,ExP))),
  356	asserta(M:'$aleph_global'(atoms_left,atoms_left(pos,ExP))),
  357	asserta(M:'$aleph_global'(last_example,last_example(pos,NP))),
  358	(M:'$aleph_global'(size,size(neg,NN))->true;NN=0),
  359	(NN > 0 -> ExN = [1-NN]; ExN = []),
  360	asserta(M:'$aleph_global'(atoms,atoms(neg,ExN))),
  361	asserta(M:'$aleph_global'(atoms_left,atoms_left(neg,ExN))),
  362	asserta(M:'$aleph_global'(last_example,last_example(neg,NN))),
  363	set_lazy_recalls(M),
  364	(setting(prior,_,M) -> true;
  365		normalise_distribution([NP-pos,NN-neg],Prior),
  366		set(prior,Prior,M)
  367	).
  368
  369assert_all([],_M,[]).
  370
  371assert_all([H|T],M,[HRef|TRef]):-
  372  assertz(M:H,HRef),
  373  assert_all(T,M,TRef).
  374
  375assert_all([],[]).
  376
  377assert_all([H|T],[HRef|TRef]):-
  378  assertz(H,HRef),
  379  assert_all(T,TRef).
  380
  381print_arr([]).
  382print_arr([H|T]):-
  383	write(H),print_arr(T),nl.
  384	
  385
  386
  387/*
  388theory_induce(Theory):-
  389	aleph_input_mod(M),
  390	induce,
  391	show(Theory).
  392*/
  393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  394% C O M P I L E R   S P E C I F I C
  395
  396
  397prolog_type(yap):-
  398	predicate_property(yap_flag(_,_),built_in), !.
  399prolog_type(swi).
  400
  401init(yap):-
  402	source,
  403	system_predicate(false,false), hide(false),
  404	style_check(single_var),
  405	% yap_flag(profiling,on),
  406	assert_static((aleph_random(X):- X is random)),
  407	(predicate_property(alarm(_,_,_),built_in) ->
  408		assert_static((remove_alarm(X):- alarm(0,_,_)));
  409		assert_static(alarm(_,_,_)),
  410		assert_static(remove_alarm(_))),
  411	assert_static((aleph_consult(F):- consult(F))),
  412	assert_static((aleph_reconsult(F):- reconsult(F))),
  413        (predicate_property(thread_local(_),built_in) -> true;
  414		assert_static(thread_local(_))),
  415	assert_static(broadcast(_)),
  416	assert_static((aleph_background_predicate(Lit):-
  417				predicate_property(Lit,P),
  418				((P = static); (P = dynamic); (P = built_in)), !)),
  419	(predicate_property(delete_file(_),built_in) -> true;
  420		assert_static(delete_file(_))).
  421
  422init(swi,M):-
  423	%redefine_system_predicate(false),
  424	style_check(+singleton),
  425	style_check(-discontiguous),
  426	M:dynamic(aleph_false/0),
  427	M:dynamic(example/3),
  428	assert((depth_bound_call(G,L,M):-
  429			call_with_depth_limit(M:G,L,R),
  430			R \= depth_limit_exceeded)),
  431	(predicate_property(numbervars(_,_,_),built_in) -> true;
  432		assert((numbervars(A,B,C):- numbervars(A,'$VAR',B,C)))),
  433	assert((system(X):- shell(X))),
  434	assert((exists(X):- exists_file(X))), 
  435	assert((aleph_reconsult(F):- consult(F))),
  436	%assert((aleph_random(X):- I = 1000000, X is float(random(I-1))/float(I))),
  437        (predicate_property(thread_local(_),built_in) -> true;
  438		assert(thread_local(_))),
  439	
  440	(predicate_property(delete_file(_),built_in) -> true;
  441		assert(delete_file(_))).
  442
  443aleph_background_predicate(Lit,M):-
  444				predicate_property(M:Lit,P),
  445				((P=interpreted);(P=built_in)), !.
  446
  447aleph_consult(X,M):- aleph_open(X,read,S), repeat,
  448			read(S,F), (F = end_of_file -> close(S), !;
  449					assertz(M:F),fail).
 aleph_random(-X:float) is det
Returns a random number in [0,1) /
  455aleph_random(X):- I = 1000000, X is float(random(I-1))/float(I).
  456
  457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  458% A L E P H
  459
  460
  461aleph_version(5).
  462aleph_version_date('Sun Mar 11 03:25:37 UTC 2007').
  463aleph_manual('http://www.comlab.ox.ac.uk/oucl/groups/machlearn/Aleph/index.html').
  464
  465
  466
  467:- thread_local aleph_input_mod/1.  468
  469
  470
  471:- multifile prune/1.  472:- multifile refine/2.  473:- multifile cost/3.  474:- multifile prove/2.  475:- multifile redundant/2.  476:- multifile text/2.  477
  478
  479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  480% C O N S T R U C T   B O T T O M
  481
  482% get_atoms(+Preds,+Depth,+MaxDepth,+Last,-LastLit)
  483% layered generation of ground atoms to add to bottom clause
  484%	Preds is list of PName/Arity entries obtained from the determinations
  485%	Depth is current variable-chain depth
  486%	MaxDepth is maximum allowed variable chain depth (i setting)
  487%	Last is last atom number so far
  488%	Lastlit is atom number after all atoms to MaxDepth have been generated
  489
  490% get_atoms(L,1,Ival,Last1,Last) che diventa
  491% get_atoms([short/1,...],1,2,1,-LastLit).
  492
  493get_atoms([],_,_,Last,Last,_M):- !.
  494get_atoms(Preds,Depth,MaxDepth,Last,LastLit,M):-
  495	Depth =< MaxDepth,
  496	Depth0 is Depth - 1,
  497	M:'$aleph_sat_terms'(_,Depth0,_,_),	% new terms generated ?
  498	!,
  499	get_atoms1(Preds,Depth,MaxDepth,Last,Last1,M),
  500	Depth1 is Depth + 1,
  501	get_atoms(Preds,Depth1,MaxDepth,Last1,LastLit,M).
  502get_atoms(_,_,_,Last,Last,_M).
  503
  504% auxiliary predicate used by get_atoms/5
  505get_atoms1([],_,_,Last,Last,_M).
  506% get_atoms1([short/1|...],1,2,1,-LastLit,M).
  507get_atoms1([Pred|Preds],Depth,MaxDepth,Last,LastLit,M):-
  508	gen_layer(Pred,Depth,M),
  509	flatten(Depth,MaxDepth,Last,Last1,M),
  510	get_atoms1(Preds,Depth,MaxDepth,Last1,LastLit,M).
  511
  512% flatten(+Depth,+MaxDepth,+Last,-LastLit)
  513% flatten a set of ground atoms by replacing all in/out terms with variables
  514%	constants are wrapped in a special term called aleph_const(...)
  515%	eg suppose p/3 had modes p(+char,+char,#int)
  516%	then p(a,a,3) becomes p(X,X,aleph_const(3))
  517% ground atoms to be flattened are assumed to be in the i.d.b atoms
  518% vars and terms are actually integers which are stored in vars/terms databases
  519%	so eg above actually becomes p(1,1,aleph_const(3)).
  520%	where variable 1 stands for term 2 (say) which in turn stands for a
  521%	Depth is current variable-chain depth
  522%	MaxDepth is maximum allowed variable chain depth (i setting)
  523%	Last is last atom number so far
  524%	Lastlit is atom number after ground atoms here have been flattened
  525% If permute_bottom is set to true, then the order of ground atoms is
  526% shuffled. The empirical utility of doing this has been investigated by
  527% P. Schorn in "Random Local Bottom Clause Permutations for Better Search Space
  528% Exploration in Progol-like ILP Systems.", 16th International Conference on
  529% ILP (ILP 2006).
  530flatten(Depth,MaxDepth,Last,Last1,M):-
  531	retractall(M:'$aleph_local'(flatten_num,_)),
  532	asserta(M:'$aleph_local'(flatten_num,Last)),
  533	M:'$aleph_sat_atom'(_,_),!,
  534	(setting(permute_bottom,Permute,M) -> true; Permute = false),
  535	flatten_atoms(Permute,Depth,MaxDepth,Last1,M).
  536flatten(_,_,_,Last,M):-
  537	retract(M:'$aleph_local'(flatten_num,Last)), !.
  538
  539flatten_atoms(true,Depth,MaxDepth,Last1,M):-
  540	findall(L-Mod,retract(M:'$aleph_sat_atom'(L,Mod)),LitModes),
  541	aleph_rpermute(LitModes,PLitModes),
  542	aleph_member(Lit1-Mode,PLitModes),
  543	retract(M:'$aleph_local'(flatten_num,LastSoFar)),
  544	(Lit1 = not(Lit) -> Negated = true; Lit = Lit1, Negated = false),
  545	flatten_atom(Depth,MaxDepth,Lit,Negated,Mode,LastSoFar,Last1,M),
  546	asserta(M:'$aleph_local'(flatten_num,Last1)),
  547	fail.
  548flatten_atoms(false,Depth,MaxDepth,Last1,M):-
  549	repeat,
  550	retract(M:'$aleph_sat_atom'(Lit1,Mode)),
  551	retract(M:'$aleph_local'(flatten_num,LastSoFar)),
  552	(Lit1 = not(Lit) -> Negated = true; Lit = Lit1, Negated = false),
  553	flatten_atom(Depth,MaxDepth,Lit,Negated,Mode,LastSoFar,Last1,M),
  554	asserta(M:'$aleph_local'(flatten_num,Last1)),
  555	(M:'$aleph_sat_atom'(_,_) ->
  556			fail;
  557			retract(M:'$aleph_local'(flatten_num,Last1))), !.
  558flatten_atoms(_,_,_,Last,M):-
  559	retract(M:'$aleph_local'(flatten_num,Last)), !.
  560
  561
  562% flatten_atom(+Depth,+Depth1,+Lit,+Negated,+Mode,+Last,-Last1)
  563%	update lits database by adding ``flattened atoms''. This involves:
  564%	replacing ground terms at +/- positions in Lit with variables
  565%	and wrapping # positions in Lit within a special term stucture
  566%	Mode contains actual mode and term-place numbers and types for +/-/# 
  567%	Last is the last literal number in the lits database at present
  568%	Last1 is the last literal number after the update
  569flatten_atom(Depth,Depth1,Lit,Negated,Mode,Last,Last1,M):-
  570	arg(3,Mode,O), arg(4,Mode,C),
  571	integrate_args(Depth,Lit,O,M),
  572	integrate_args(Depth,Lit,C,M),
  573	(Depth = Depth1 -> CheckOArgs = true; CheckOArgs = false),
  574	flatten_lits(Lit,CheckOArgs,Depth,Negated,Mode,Last,Last1,M).
  575
  576% variabilise literals by replacing terms with variables
  577% if var splitting is on then new equalities are introduced into bottom clause
  578% if at final i-layer, then literals with o/p args that do not contain at least
  579% 	one output var from head are discarded
  580flatten_lits(Lit,CheckOArgs,Depth,Negated,Mode,Last,_,M):-
  581	functor(Lit,Name,Arity),
  582	asserta(M:'$aleph_local'(flatten_lits,Last)),
  583	Depth1 is Depth - 1,
  584	functor(OldFAtom,Name,Arity),
  585	flatten_lit(Lit,Mode,OldFAtom,_,_,M),
  586	functor(FAtom,Name,Arity),
  587	apply_equivs(Depth1,Arity,OldFAtom,FAtom,M),
  588	retract(M:'$aleph_local'(flatten_lits,OldLast)),
  589	(CheckOArgs = true -> 
  590		arg(3,Mode,Out),
  591		get_vars(FAtom,Out,OVars),
  592		(in_path(OVars,M) ->
  593			add_new_lit(Depth,FAtom,Mode,OldLast,Negated,NewLast,M);
  594			NewLast = OldLast) ;
  595		add_new_lit(Depth,FAtom,Mode,OldLast,Negated,NewLast,M)),
  596	asserta(M:'$aleph_local'(flatten_lits,NewLast)),
  597	fail.
  598flatten_lits(_,_,_,_,_,_,Last1,M):-
  599	retract(M:'$aleph_local'(flatten_lits,Last1)).
  600
  601
  602% flatten_lit(+Lit,+Mode,+FAtom,-IVars,-OVars)
  603% variabilise Lit as FAtom
  604%	Mode contains actual mode and 
  605%	In, Out, Const positions as term-place numbers with types
  606% 	replace ground terms with integers denoting variables
  607%	or special terms denoting constants
  608% 	variable numbers arising from variable splits are disallowed
  609%	returns Input and Output variable numbers
  610flatten_lit(Lit,mode(Mode,In,Out,Const),FAtom,IVars,OVars,M):-
  611	functor(Mode,_,Arity),
  612	once(copy_modeterms(Mode,FAtom,Arity)),
  613	flatten_vars(In,Lit,FAtom,IVars,M),
  614	flatten_vars(Out,Lit,FAtom,OVars,M),
  615	flatten_consts(Const,Lit,FAtom).
  616
  617% flatten_vars(+TPList,+Lit,+FAtom,-Vars):-
  618% FAtom is Lit with terms-places in TPList replaced by variables
  619flatten_vars([],_,_,[],_M).
  620flatten_vars([Pos/Type|Rest],Lit,FAtom,[Var|Vars],M):-
  621	tparg(Pos,Lit,Term),
  622	M:'$aleph_sat_terms'(TNo,_,Term,Type),
  623	M:'$aleph_sat_vars'(Var,TNo,_,_),
  624	\+(M:'$aleph_sat_varscopy'(Var,_,_)),
  625	tparg(Pos,FAtom,Var),
  626	flatten_vars(Rest,Lit,FAtom,Vars,M).
  627
  628% replace a list of terms at places marked by # in the modes
  629% with a special term structure denoting a constant
  630flatten_consts([],_,_).
  631flatten_consts([Pos/_|Rest],Lit,FAtom):-
  632	tparg(Pos,Lit,Term),
  633	tparg(Pos,FAtom,aleph_const(Term)),
  634	flatten_consts(Rest,Lit,FAtom).
  635
  636% in_path(+ListOfOutputVars)
  637% check to avoid generating useless literals in the last i layer
  638in_path(OVars,M):-
  639	M:'$aleph_sat'(hovars,Vars), !,
  640	(Vars=[];OVars=[];intersects(Vars,OVars)).
  641in_path(_,_M).
  642
  643% update_equivs(+VariableEquivalences,+IDepth)
  644% update variable equivalences created at a particular i-depth
  645% is non-empty only if variable splitting is allowed
  646update_equivs([],_,_M):- !.
  647update_equivs(Equivs,Depth,M):-
  648	retract(M:'$aleph_sat_varsequiv'(Depth,Eq1)), !,
  649	update_equiv_lists(Equivs,Eq1,Eq2),
  650	asserta(M:'$aleph_sat_varsequiv'(Depth,Eq2)).
  651update_equivs(Equivs,Depth,M):-
  652	Depth1 is Depth - 1,
  653	get_equivs(Depth1,Eq1,M),
  654	update_equiv_lists(Equivs,Eq1,Eq2,M),
  655	asserta(M:'$aleph_sat_varsequiv'(Depth,Eq2)).
  656
  657update_equiv_lists([],E,E):- !.
  658update_equiv_lists([Var/E1|Equivs],ESoFar,E):-
  659	aleph_delete(Var/E2,ESoFar,ELeft), !,
  660	update_list(E1,E2,E3),
  661	update_equiv_lists(Equivs,[Var/E3|ELeft],E).
  662update_equiv_lists([Equiv|Equivs],ESoFar,E):-
  663	update_equiv_lists(Equivs,[Equiv|ESoFar],E).
  664
  665% get variable equivalences at a particular depth
  666% recursively descend to greatest depth below this for which equivs exist
  667% also returns the database reference of entry
  668get_equivs(Depth,[],_M):-
  669	Depth < 0, !.
  670get_equivs(Depth,Equivs,M):-
  671	M:'$aleph_sat_varsequiv'(Depth,Equivs), !.
  672get_equivs(Depth,E,M):-
  673	Depth1 is Depth - 1,
  674	get_equivs(Depth1,E,M).
  675
  676% apply equivalences inherited from Depth to a flattened literal
  677% if no variable splitting, then succeeds only once
  678apply_equivs(Depth,Arity,Old,New,M):-
  679	get_equivs(Depth,Equivs,M),
  680	rename(Arity,Equivs,[],Old,New).
  681
  682% rename args using list of Var/Equivalences
  683rename(_,[],_,L,L):- !.
  684rename(0,_,_,_,_):- !.
  685rename(Pos,Equivs,Subst0,Old,New):-
  686        arg(Pos,Old,OldVar),
  687        aleph_member(OldVar/Equiv,Equivs), !,
  688        aleph_member(NewVar,Equiv),
  689        arg(Pos,New,NewVar),
  690        Pos1 is Pos - 1,
  691        rename(Pos1,Equivs,[OldVar/NewVar|Subst0],Old,New).
  692rename(Pos,Equivs,Subst0,Old,New):-
  693        arg(Pos,Old,OldVar),
  694        (aleph_member(OldVar/NewVar,Subst0) ->
  695                arg(Pos,New,NewVar);
  696                arg(Pos,New,OldVar)),
  697        Pos1 is Pos - 1,
  698        rename(Pos1,Equivs,Subst0,Old,New).
  699
  700
  701% add a new literal to lits database
  702% performs variable splitting if splitvars is set to true
  703add_new_lit(Depth,FAtom,Mode,OldLast,Negated,NewLast,M):-
  704	arg(1,Mode,M1),
  705	functor(FAtom,Name,Arity),
  706	functor(SplitAtom,Name,Arity),
  707	once(copy_modeterms(M1,SplitAtom,Arity)),
  708	arg(2,Mode,In), arg(3,Mode,Out), arg(4,Mode,Const),
  709        split_vars(Depth,FAtom,In,Out,Const,SplitAtom,IVars,OVars,Equivs,M),
  710        update_equivs(Equivs,Depth,M),
  711        add_lit(OldLast,Negated,SplitAtom,In,Out,IVars,OVars,LitNum,M),
  712        insert_eqs(Equivs,Depth,LitNum,NewLast,M), !.
  713
  714% modify the literal database: check if performing lazy evaluation
  715% of bottom clause, and update input and output terms in literal
  716add_lit(Last,Negated,FAtom,I,O,_,_,Last,M):-
  717	setting(construct_bottom,CBot,M),
  718	(CBot = false ; CBot = reduction), 
  719	(Negated = true -> Lit = not(FAtom); Lit = FAtom),
  720	M:'$aleph_sat_litinfo'(_,0,Lit,I,O,_), !.
  721add_lit(Last,Negated,FAtom,In,Out,IVars,OVars,LitNum,M):-
  722	LitNum is Last + 1,
  723	update_iterms(LitNum,IVars,M),
  724	update_oterms(LitNum,OVars,[],Dependents,M),
  725	add_litinfo(LitNum,Negated,FAtom,In,Out,Dependents,M),
  726	assertz(M:'$aleph_sat_ivars'(LitNum,IVars)),
  727	assertz(M:'$aleph_sat_ovars'(LitNum,OVars)), !.
  728
  729
  730% update lits database after checking that the atom does not exist
  731% used during updates of lit database by lazy evaluation
  732update_lit(LitNum,true,FAtom,I,O,D,M):-
  733	M:'$aleph_sat_litinfo'(LitNum,0,not(FAtom),I,O,D), !.
  734update_lit(LitNum,false,FAtom,I,O,D,M):-
  735	M:'$aleph_sat_litinfo'(LitNum,0,FAtom,I,O,D), !.
  736update_lit(LitNum,Negated,FAtom,I,O,D,M):-
  737	gen_nlitnum(LitNum,M),
  738	add_litinfo(LitNum,Negated,FAtom,I,O,D,M), 
  739	get_vars(FAtom,I,IVars),
  740	get_vars(FAtom,O,OVars),
  741	assertz(M:'$aleph_sat_ivars'(LitNum,K,IVars)),
  742	assertz(M:'$aleph_sat_ovars'(LitNum,K,OVars)), !.
  743
  744% add a literal to lits database without checking
  745add_litinfo(LitNum,true,FAtom,I,O,D,M):-
  746	!,
  747	assertz(M:'$aleph_sat_litinfo'(LitNum,0,not(FAtom),I,O,D)).
  748add_litinfo(LitNum,_,FAtom,I,O,D,M):-
  749	assertz(M:'$aleph_sat_litinfo'(LitNum,0,FAtom,I,O,D)).
  750	
  751% update database with input terms of literal
  752update_iterms(_,[],_M).
  753update_iterms(LitNum,[VarNum|Vars],M):-
  754	retract(M:'$aleph_sat_vars'(VarNum,TNo,I,O)),
  755	update(I,LitNum,NewI),
  756	asserta(M:'$aleph_sat_vars'(VarNum,TNo,NewI,O)),
  757	update_dependents(LitNum,O,M),
  758	update_iterms(LitNum,Vars,M).
  759
  760% update database with output terms of literal
  761% return list of dependent literals
  762update_oterms(_,[],Dependents,Dependents,_M).
  763update_oterms(LitNum,[VarNum|Vars],DSoFar,Dependents,M):-
  764	retract(M:'$aleph_sat_vars'(VarNum,TNo,I,O)),
  765	update(O,LitNum,NewO),
  766	asserta(M:'$aleph_sat_vars'(VarNum,TNo,I,NewO)),
  767	update_list(I,DSoFar,D1),
  768	update_oterms(LitNum,Vars,D1,Dependents,M).
  769
  770% update Dependent list of literals with LitNum
  771update_dependents(_,[],_M).
  772update_dependents(LitNum,[Lit|Lits],M):-
  773	retract(M:'$aleph_sat_litinfo'(Lit,Depth,Atom,ITerms,OTerms,Dependents)),
  774	update(Dependents,LitNum,NewD),
  775	asserta(M:'$aleph_sat_litinfo'(Lit,Depth,Atom,ITerms,OTerms,NewD)),
  776	update_dependents(LitNum,Lits,M).
  777
  778% update dependents of head with literals that are simply generators
  779% 	that is, literals that require no input args
  780update_generators(M):-
  781	findall(L,(M:'$aleph_sat_litinfo'(L,_,_,[],_,_),L>1),GList),
  782	GList \= [], !,
  783	retract(M:'$aleph_sat_litinfo'(1,Depth,Lit,I,O,D)),
  784	aleph_append(D,GList,D1),
  785	asserta(M:'$aleph_sat_litinfo'(1,Depth,Lit,I,O,D1)).
  786update_generators(_M).
  787
  788% mark literals 
  789mark_lits(Lits,M):-
  790	aleph_member(Lit,Lits),
  791	asserta(M:'$aleph_local'(marked,Lit/0)),
  792	fail.
  793mark_lits(_,_M).
  794	
  795% recursively mark literals with minimum depth to bind output vars in head
  796mark_lits([],_,_,_M).
  797mark_lits(Lits,OldVars,Depth,M):-
  798	mark_lits(Lits,Depth,true,[],Predecessors,OldVars,NewVars,M),
  799	aleph_delete_list(Lits,Predecessors,P1),
  800	Depth1 is Depth + 1,
  801	mark_lits(P1,NewVars,Depth1,M).
  802
  803mark_lits([],_,_,P,P,V,V,_M).
  804mark_lits([Lit|Lits],Depth,GetPreds,PSoFar,P,VSoFar,V,M):-
  805	retract(M:'$aleph_local'(marked,Lit/Depth0)), !,
  806	(Depth < Depth0 ->
  807		mark_lit(Lit,Depth,GetPreds,VSoFar,P1,V2,M),
  808		update_list(P1,PSoFar,P2),
  809		mark_lits(Lits,Depth,GetPreds,P2,P,V2,V,M);
  810		asserta(M:'$aleph_local'(marked,Lit/Depth0)),
  811		mark_lits(Lits,Depth,GetPreds,PSoFar,P,VSoFar,V,M)).
  812mark_lits([Lit|Lits],Depth,GetPreds,PSoFar,P,VSoFar,V,M):-
  813	mark_lit(Lit,Depth,GetPreds,VSoFar,P1,V2,M), !,
  814	update_list(P1,PSoFar,P2),
  815	mark_lits(Lits,Depth,GetPreds,P2,P,V2,V,M).
  816mark_lits([_|Lits],Depth,GetPreds,PSoFar,P,VSoFar,V,M):-
  817	mark_lits(Lits,Depth,GetPreds,PSoFar,P,VSoFar,V,M).
  818
  819mark_lit(Lit,Depth,GetPreds,VSoFar,P1,V1,M):-
  820	retract(M:'$aleph_sat_litinfo'(Lit,_,Atom,I,O,D)),
  821	asserta(M:'$aleph_local'(marked,Lit/Depth)),
  822	asserta(M:'$aleph_sat_litinfo'(Lit,Depth,Atom,I,O,D)),
  823	(GetPreds = false ->
  824		P1 = [],
  825		V1 = VSoFar;
  826		get_vars(Atom,O,OVars),
  827		update_list(OVars,VSoFar,V1),
  828		get_predicates(D,V1,D1,M),
  829		mark_lits(D1,Depth,false,[],_,VSoFar,_,M),
  830		get_vars(Atom,I,IVars),
  831		get_predecessors(IVars,[],P1,M)).
  832
  833% mark lits that produce outputs that are not used by any other literal
  834mark_floating_lits(Lit,Last,_M):-
  835	Lit > Last, !.
  836mark_floating_lits(Lit,Last,M):-
  837	M:'$aleph_sat_litinfo'(Lit,_,_,_,O,D),
  838	O \= [],
  839	(D = []; D = [Lit]), !,
  840	asserta(M:'$aleph_local'(marked,Lit/0)),
  841	Lit1 is Lit + 1,
  842	mark_floating_lits(Lit1,Last,M).
  843mark_floating_lits(Lit,Last,M):-
  844	Lit1 is Lit + 1,
  845	mark_floating_lits(Lit1,Last,M).
  846	
  847% mark lits in bottom clause that are specified redundant by user
  848% requires definition of redundant/2 that have distinguished first arg ``bottom''
  849mark_redundant_lits(Lit,Last,_M):-
  850	Lit > Last, !.
  851mark_redundant_lits(Lit,Last,M):-
  852	get_pclause([Lit],[],Atom,_,_,_,M),
  853	redundant(bottom,Atom,M), !,
  854	asserta(M:'$aleph_local'(marked,Lit/0)),
  855	Lit1 is Lit + 1,
  856	mark_redundant_lits(Lit1,Last,M).
  857mark_redundant_lits(Lit,Last,M):-
  858	Lit1 is Lit + 1,
  859	mark_redundant_lits(Lit1,Last,M).
  860
  861% get literals that are linked and do not link to any others (ie predicates)
  862get_predicates([],_,[],_M).
  863get_predicates([Lit|Lits],Vars,[Lit|T],M):-
  864	M:'$aleph_sat_litinfo'(Lit,_,Atom,I,_,[]),
  865	get_vars(Atom,I,IVars),
  866	aleph_subset1(IVars,Vars), !,
  867	get_predicates(Lits,Vars,T,M).
  868get_predicates([_|Lits],Vars,T,M):-
  869	get_predicates(Lits,Vars,T,M).
  870
  871% get all predecessors in the bottom clause of a set of literals
  872get_predecessors([],[],_M).
  873get_predecessors([Lit|Lits],P,M):-
  874	(Lit = 1 -> Pred = [];
  875		get_ivars1(false,Lit,IVars,M),
  876		get_predecessors(IVars,[],Pred,M)),
  877	get_predecessors(Pred,PPred,M),
  878	update_list(Pred,PPred,P1),
  879	get_predecessors(Lits,P2,M),
  880	update_list(P2,P1,P).
  881
  882% get list of literals in the bottom clause that produce a set of vars
  883get_predecessors([],P,P,_M).
  884get_predecessors([Var|Vars],PSoFar,P,M):-
  885	M:'$aleph_sat_vars'(Var,_,_,O),
  886	update_list(O,PSoFar,P1),
  887	get_predecessors(Vars,P1,P,M).
  888
  889% removal of literals in bottom clause by negative-based reduction.
  890% A greedy strategy is employed, as implemented within the ILP system
  891% Golem (see Muggleton and Feng, "Efficient induction
  892% of logic programs", Inductive Logic Programming, S. Muggleton (ed.),
  893% AFP Press). In this, given a clause H:- B1, B2,...Bn, let Bi be the
  894% first literal s.t. H:-B1,...,Bi covers no more than the allowable number
  895% of negatives. The clause H:- Bi,B1,...,Bi-1 is then reduced. The
  896% process continues until there is no change in the length of a clause
  897% within an iteration. The algorithm is O(n^2).
  898rm_nreduce(Last,N,M):-
  899	setting(nreduce_bottom,true,M), !,
  900	get_litnums(1,Last,BottomLits,M),
  901        M:'$aleph_global'(atoms,atoms(neg,Neg)),
  902	setting(depth,Depth,M),
  903	setting(prooftime,Time,M),
  904	setting(proof_strategy,Proof,M),
  905	setting(noise,Noise,M),
  906	neg_reduce(BottomLits,Neg,Last,Depth/Time/Proof,Noise,M),
  907	get_marked(1,Last,Lits,M),
  908	length(Lits,N),
  909	p1_message('negative-based removal'), p_message(N/Last).
  910rm_nreduce(_,0,_M).
  911
  912neg_reduce([Head|Body],Neg,Last,DepthTime,Noise,M):-
  913	get_pclause([Head],[],Clause,TV,_,_,M),
  914	neg_reduce(Body,Clause,TV,2,Neg,DepthTime,Noise,NewLast,M),
  915	NewLast \= Last, !,
  916	NewLast1 is NewLast - 1,
  917	aleph_remove_n(NewLast1,[Head|Body],Prefix,[LastLit|Rest]),
  918	mark_lits(Rest,M),
  919	insert_lastlit(LastLit,Prefix,Lits1),
  920	neg_reduce(Lits1,Neg,NewLast,DepthTime,Noise,M).
  921neg_reduce(_,_,_,_,_,_M).
  922
  923neg_reduce([],_,_,N,_,_,_,N).
  924neg_reduce([L1|Lits],C,TV,N,Neg,ProofFlags,Noise,LastLit,M):-
  925	get_pclause([L1],TV,Lit1,TV1,_,_,M),
  926	extend_clause(C,Lit1,Clause,M),
  927        prove(ProofFlags,neg,Clause,Neg,NegCover,Count,M),
  928	Count > Noise, !,
  929	N1 is N + 1,
  930	neg_reduce(Lits,Clause,TV1,N1,NegCover,ProofFlags,Noise,LastLit,M).
  931neg_reduce(_,_,_,N,_,_,_,N,_M).
  932
  933% insert_lastlit(LastLit,[1|Lits],Lits1):-
  934	% find_last_ancestor(Lits,LastLit,1,2,Last),
  935	% aleph_remove_n(Last,[1|Lits],Prefix,Suffix),
  936	% aleph_append([LastLit|Suffix],Prefix,Lits1).
  937
  938insert_lastlit(LastLit,Lits,Lits1,M):-
  939	get_predecessors([LastLit],Prefix,M),
  940	aleph_delete_list(Prefix,Lits,Suffix),
  941	aleph_append([LastLit|Suffix],Prefix,Lits1).
  942
  943	
  944find_last_ancestor([],_,Last,_,Last,_M):- !.
  945find_last_ancestor([Lit|Lits],L,_,LitNum,Last,M):-
  946	M:'$aleph_sat_litinfo'(Lit,_,_,_,_,D), 
  947	aleph_member1(L,D), !,
  948	NextLit is LitNum + 1,
  949	find_last_ancestor(Lits,L,LitNum,NextLit,Last,M).
  950find_last_ancestor([_|Lits],L,Last0,LitNum,Last,M):-
  951	NextLit is LitNum + 1,
  952	find_last_ancestor(Lits,L,Last0,NextLit,Last,M).
  953
  954% removal of literals that are repeated because of mode differences
  955rm_moderepeats(_,_,M):-
  956	M:'$aleph_sat_litinfo'(Lit1,_,Pred1,_,_,_),
  957	M:'$aleph_sat_litinfo'(Lit2,_,Pred1,_,_,_),
  958	Lit1 >= 1, Lit2 > Lit1,
  959	retract(M:'$aleph_sat_litinfo'(Lit2,_,Pred1,_,_,_)),
  960	asserta(M:'$aleph_local'(marked,Lit2/0)),
  961	fail.
  962rm_moderepeats(Last,N,M):-
  963	M:'$aleph_local'(marked,_), !,
  964	get_marked(1,Last,Lits,M),
  965	length(Lits,N),
  966	p1_message('repeated literals'), p_message(N/Last),
  967	remove_lits(Lits,M).
  968rm_moderepeats(_,0,_M).
  969	
  970% removal of symmetric literals
  971rm_symmetric(_,_,M):-
  972	M:'$aleph_global'(symmetric,_),
  973	M:'$aleph_sat_litinfo'(Lit1,_,Pred1,[I1|T1],_,_),
  974	is_symmetric(Pred1,Name,Arity,M),
  975	get_vars(Pred1,[I1|T1],S1),
  976	M:'$aleph_sat_litinfo'(Lit2,_,Pred2,[I2|T2],_,_),
  977	Lit1 \= Lit2,
  978	is_symmetric(Pred2,Name,Arity,M),
  979	Pred1 =.. [_|Args1],
  980	Pred2 =.. [_|Args2],
  981	symmetric_match(Args1,Args2),
  982	get_vars(Pred2,[I2|T2],S2),
  983	equal_set(S1,S2),
  984	asserta(M:'$aleph_local'(marked,Lit2/0)),
  985	retract(M:'$aleph_sat_litinfo'(Lit2,_,Pred2,[I2|T2],_,_)),
  986	fail.
  987rm_symmetric(Last,N,M):-
  988	M:'$aleph_local'(marked,_), !,
  989	get_marked(1,Last,Lits,M),
  990	length(Lits,N),
  991	p1_message('symmetric literals'), p_message(N/Last),
  992	remove_lits(Lits,M).
  993rm_symmetric(_,0,_M).
  994
  995is_symmetric(not(Pred),not(Name),Arity,M):-
  996	!,
  997	functor(Pred,Name,Arity),
  998	M:'$aleph_global'(symmetric,symmetric(Name/Arity)).
  999is_symmetric(Pred,Name,Arity,M):-
 1000	functor(Pred,Name,Arity),
 1001	M:'$aleph_global'(symmetric,symmetric(Name/Arity)).
 1002
 1003symmetric_match([],[]).
 1004symmetric_match([aleph_const(Term)|Terms1],[aleph_const(Term)|Terms2]):-
 1005	!,
 1006	symmetric_match(Terms1,Terms2).
 1007symmetric_match([Term1|Terms1],[Term2|Terms2]):-
 1008	integer(Term1), integer(Term2),
 1009	symmetric_match(Terms1,Terms2).
 1010	
 1011% removal of literals that are repeated because of commutativity
 1012rm_commutative(_,_,M):-
 1013	M:'$aleph_global'(commutative,commutative(Name/Arity)),
 1014	p1_message('checking commutative literals'), p_message(Name/Arity),
 1015	functor(Pred,Name,Arity), functor(Pred1,Name,Arity),
 1016	M:'$aleph_sat_litinfo'(Lit1,_,Pred,[I1|T1],O1,_),
 1017        % check for marked literals
 1018	% (SWI-Prolog specific: suggested by Vasili Vrubleuski)
 1019        \+(M:'$aleph_local'(marked,Lit1/0)),
 1020	get_vars(Pred,[I1|T1],S1),
 1021	M:'$aleph_sat_litinfo'(Lit2,_,Pred1,[I2|T2],O2,_),
 1022	Lit1 \= Lit2 ,
 1023	O1 = O2,
 1024	get_vars(Pred1,[I2|T2],S2),
 1025	equal_set(S1,S2),
 1026	asserta(M:'$aleph_local'(marked,Lit2/0)),
 1027	retract(M:'$aleph_sat_litinfo'(Lit2,_,Pred1,[I2|T2],_,_)),
 1028	fail.
 1029rm_commutative(Last,N,M):-
 1030	M:'$aleph_local'(marked,_), !,
 1031	get_marked(1,Last,Lits),
 1032	length(Lits,N),
 1033	p1_message('commutative literals'), p_message(N/Last),
 1034	remove_lits(Lits).
 1035rm_commutative(_,0,_M).
 1036
 1037% recursive marking of literals that do not contribute to establishing
 1038% variable chains to output vars in the head
 1039% or produce outputs that are not used by any literal
 1040% controlled by setting flag check_useless
 1041rm_uselesslits(_,0,M):-
 1042	setting(check_useless,false,M), !.
 1043rm_uselesslits(Last,N,M):-
 1044	M:'$aleph_sat'(hovars,OVars),
 1045	OVars \= [], !,
 1046	get_predecessors(OVars,[],P,M),
 1047	M:'$aleph_sat'(hivars,IVars),
 1048	mark_lits(P,IVars,0,M),
 1049	get_unmarked(1,Last,Lits,M),
 1050	length(Lits,N),
 1051	p1_message('useless literals'), p_message(N/Last),
 1052	remove_lits(Lits,M).
 1053rm_uselesslits(_,0,_M).
 1054
 1055% call user-defined predicate redundant/2 to remove redundant
 1056% literals from bottom clause. Redundancy checking only done on request
 1057rm_redundant(_,0,M):-
 1058	setting(check_redundant,false,M), !.
 1059rm_redundant(Last,N,M):-
 1060	mark_redundant_lits(1,Last,M),
 1061	get_marked(1,Last,Lits,M),
 1062	length(Lits,N),
 1063	p1_message('redundant literals'), p_message(N/Last),
 1064	remove_lits(Lits,M).
 1065
 1066% get a list of unmarked literals
 1067get_unmarked(Lit,Last,[],_M):-
 1068	Lit > Last, !.
 1069get_unmarked(Lit,Last,Lits,M):-
 1070	retract(M:'$aleph_local'(marked,Lit/_)), !,
 1071	Next is Lit + 1,
 1072	get_unmarked(Next,Last,Lits,M).
 1073get_unmarked(Lit,Last,[Lit|Lits],M):-
 1074	retract(M:'$aleph_sat_litinfo'(Lit,_,_,_,_,_)), !,
 1075	Next is Lit + 1,
 1076	get_unmarked(Next,Last,Lits,M).
 1077get_unmarked(Lit,Last,Lits,M):-
 1078	Next is Lit + 1,
 1079	get_unmarked(Next,Last,Lits,M).
 1080
 1081% get a list of marked literals
 1082get_marked(Lit,Last,[],_M):-
 1083	Lit > Last, !.
 1084get_marked(Lit,Last,[Lit|Lits],M):-
 1085	retract(M:'$aleph_local'(marked,Lit/_)), !,
 1086	(retract(M:'$aleph_sat_litinfo'(Lit,_,_,_,_,_)) ->
 1087		true;
 1088		true),
 1089	Next is Lit + 1,
 1090	get_marked(Next,Last,Lits,M).
 1091get_marked(Lit,Last,Lits,M):-
 1092	Next is Lit + 1,
 1093	get_marked(Next,Last,Lits,M).
 1094
 1095% update descendent lists of literals by removing useless literals
 1096remove_lits(L,M):-
 1097	retract(M:'$aleph_sat_litinfo'(Lit,Depth,A,I,O,D)), 
 1098	aleph_delete_list(L,D,D1),
 1099	asserta(M:'$aleph_sat_litinfo'(Lit,Depth,A,I,O,D1)),
 1100	fail.
 1101remove_lits(_,_M).
 1102
 1103% generate a new literal at depth Depth: forced backtracking will give all lits
 1104gen_layer(Name/Arity,Depth,M):-
 1105	(Name/Arity = (not)/1 ->
 1106		M:'$aleph_global'(modeb,modeb(NSucc,not(Mode))),
 1107		functor(Mode,Name1,Arity1),
 1108		functor(Lit1,Name1,Arity1),
 1109		once(copy_modeterms(Mode,Lit1,Arity1)),
 1110		Lit = not(Lit1);
 1111		functor(Mode,Name,Arity),
 1112		functor(Lit,Name,Arity),
 1113		M:'$aleph_global'(modeb,modeb(NSucc,Mode)),
 1114		once(copy_modeterms(Mode,Lit,Arity))),
 1115	split_args(Mode,Mode,Input,Output,Constants,M),
 1116	(Input = [] -> Call1 = true, Call2 = true;
 1117		aleph_delete(Arg/Type,Input,OtherInputs),
 1118		Depth1 is Depth - 1,
 1119		construct_incall(Lit,Depth1,[Arg/Type],Call1,M),
 1120		construct_call(Lit,Depth,OtherInputs,Call2,M)),
 1121	Call1,
 1122	Call2,
 1123	aleph_background_predicate(Lit,M),
 1124	get_successes(Lit,NSucc,mode(Mode,Input,Output,Constants),M),
 1125	fail.
 1126gen_layer(_,_,_M).
 1127
 1128get_successes(Literal,1,Mo,M):-
 1129	depth_bound_call(Literal,M), 
 1130	update_atoms(Literal,Mo,M), !.
 1131get_successes(Literal,*,Mo,M):-
 1132	depth_bound_call(Literal,M), 
 1133	update_atoms(Literal,Mo,M).
 1134get_successes(Literal,N,Mo,M):-
 1135	integer(N),
 1136	N > 1,
 1137	reset_succ(M),
 1138	get_nsuccesses(Literal,N,Mo,M).
 1139
 1140% get at most N matches for a literal
 1141get_nsuccesses(Literal,N,Mo,M):-
 1142	depth_bound_call(Literal,M), 
 1143	retract(M:'$aleph_local'(last_success,Succ0)),
 1144	Succ0 < N,
 1145	Succ1 is Succ0 + 1,
 1146	update_atoms(Literal,Mo,M),
 1147	asserta(M:'$aleph_local'(last_success,Succ1)),
 1148	(Succ1 >= N -> !; true).
 1149
 1150update_atoms(Atom,Mo,M):-
 1151	M:'$aleph_sat_atom'(Atom,Mo), !.
 1152update_atoms(Atom,Mo,M):-
 1153	assertz(M:'$aleph_sat_atom'(Atom,Mo)).
 1154
 1155% call with input term that is an ouput of a previous literal
 1156construct_incall(_,_,[],true,_M):- !.
 1157construct_incall(not(Lit),Depth,Args,Call,M):-
 1158	!,
 1159	construct_incall(Lit,Depth,Args,Call,M).
 1160construct_incall(Lit,Depth,[Pos/Type],Call,M):-
 1161	!,
 1162	Call = legal_term(exact,Depth,Type,Term,M),
 1163	tparg(Pos,Lit,Term).
 1164construct_incall(Lit,Depth,[Pos/Type|Args],(Call,Calls),M):-
 1165	tparg(Pos,Lit,Term),
 1166	Call = legal_term(exact,Depth,Type,Term,M),
 1167	(var(Depth)-> construct_incall(Lit,_,Args,Calls,M);
 1168		construct_incall(Lit,Depth,Args,Calls,M)).
 1169
 1170construct_call(_,_,[],true,_M):- !.
 1171construct_call(not(Lit),Depth,Args,Call,M):-
 1172	!,
 1173	construct_call(Lit,Depth,Args,Call,M).
 1174construct_call(Lit,Depth,[Pos/Type],Call,M):-
 1175	!,
 1176	Call = legal_term(upper,Depth,Type,Term,M),
 1177	tparg(Pos,Lit,Term).
 1178construct_call(Lit,Depth,[Pos/Type|Args],(Call,Calls),M):-
 1179	tparg(Pos,Lit,Term),
 1180	Call = legal_term(upper,Depth,Type,Term,M),
 1181	construct_call(Lit,Depth,Args,Calls,M).
 1182
 1183% generator of legal terms seen so far
 1184legal_term(exact,Depth,Type,Term,M):-
 1185	M:'$aleph_sat_terms'(TNo,Depth,Term,Type),
 1186	once(M:'$aleph_sat_vars'(_,TNo,_,[_|_])).
 1187% legal_term(exact,Depth,Type,Term):-
 1188	% M:'$aleph_sat_varscopy'(NewVar,OldVar,Depth),
 1189	% once(M:'$aleph_sat_vars'(NewVar,TNo,_,_)),
 1190	% M:'$aleph_sat_terms'(TNo,_,Term,Type),_).
 1191legal_term(upper,Depth,Type,Term,M):-
 1192	M:'$aleph_sat_terms'(TNo,Depth1,Term,Type),
 1193	Depth1 \= unknown,
 1194	Depth1 < Depth,
 1195	once(M:'$aleph_sat_vars'(_,TNo,_,[_|_])).
 1196% legal_term(upper,Depth,Type,Term):-
 1197	% M:'$aleph_sat_varscopy'(NewVar,OldVar,Depth),
 1198	% once(M:'$aleph_sat_vars'(NewVar,TNo,_,_)),
 1199	% M:'$aleph_sat_terms'(TNo,Depth1,Term,Type),
 1200	% Depth1 \= unknown.
 1201
 1202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 1203% V A R I A B L E  -- S P L I T T I N G
 1204
 1205
 1206split_vars(Depth,FAtom,I,O,C,SplitAtom,IVars,OVars,Equivs,M):-
 1207	setting(splitvars,true,M), !,
 1208        get_args(FAtom,I,[],IVarList),
 1209        get_args(FAtom,O,[],OVarList),
 1210	get_var_equivs(Depth,IVarList,OVarList,IVars,OVars0,Equivs0),
 1211	(Equivs0 = [] ->
 1212		OVars = OVars0, SplitAtom = FAtom, Equivs = Equivs0;
 1213		functor(FAtom,Name,Arity),
 1214		functor(SplitAtom,Name,Arity),
 1215		copy_args(FAtom,SplitAtom,I),
 1216		copy_args(FAtom,SplitAtom,C),
 1217		rename_ovars(O,Depth,FAtom,SplitAtom,Equivs0,Equivs),
 1218		get_argterms(SplitAtom,O,[],OVars)).
 1219	% write('splitting: '), write(FAtom), write(' to: '), write(SplitAtom), nl.
 1220split_vars(_,FAtom,I,O,_,FAtom,IVars,OVars,[],_M):-
 1221	get_vars(FAtom,I,IVars),
 1222	get_vars(FAtom,O,OVars).
 1223
 1224% get equivalent classes of variables from co-references 
 1225get_var_equivs(Depth,IVarList,OVarList,IVars,OVars,Equivs):-
 1226	sort(IVarList,IVars),
 1227	sort(OVarList,OVars),
 1228	(Depth = 0 ->
 1229		intersect1(IVars,OVarList,IOCoRefs,_),
 1230		get_repeats(IVarList,IOCoRefs,ICoRefs);
 1231		intersect1(IVars,OVarList,ICoRefs,_)),
 1232	get_repeats(OVarList,ICoRefs,CoRefs),
 1233	add_equivalences(CoRefs,Depth,Equivs).
 1234
 1235add_equivalences([],_,[]).
 1236add_equivalences([Var|Vars],Depth,[Var/E|Rest]):-
 1237	% (Depth = 0 -> E = []; E = [Var]),
 1238	E = [Var],
 1239	add_equivalences(Vars,Depth,Rest).
 1240
 1241
 1242get_repeats([],L,L).
 1243get_repeats([Var|Vars],Ref1,L):-
 1244	aleph_member1(Var,Vars), !,
 1245	update(Ref1,Var,Ref2),
 1246	get_repeats(Vars,Ref2,L).
 1247get_repeats([_|Vars],Ref,L):-
 1248	get_repeats(Vars,Ref,L).
 1249
 1250% rename all output vars that are co-references
 1251% updates vars database and return equivalent class of variables
 1252rename_ovars([],_,_,_,L,L).
 1253rename_ovars([ArgNo|Args],Depth,Old,New,CoRefs,Equivalences):-
 1254	(ArgNo = Pos/_ -> true; Pos = ArgNo),
 1255	tparg(Pos,Old,OldVar),
 1256	aleph_delete(OldVar/Equiv,CoRefs,Rest), !,
 1257	copy_var(OldVar,NewVar,Depth),
 1258	tparg(Pos,New,NewVar),
 1259	rename_ovars(Args,Depth,Old,New,[OldVar/[NewVar|Equiv]|Rest],Equivalences).
 1260rename_ovars([ArgNo|Args],Depth,Old,New,CoRefs,Equivalences):-
 1261	(ArgNo = Pos/_ -> true; Pos = ArgNo),
 1262	tparg(Pos,Old,OldVar),
 1263	tparg(Pos,New,OldVar),
 1264	rename_ovars(Args,Depth,Old,New,CoRefs,Equivalences).
 1265
 1266% create new  equalities to  allow co-references to re-appear in search
 1267insert_eqs([],_,L,L,_M).
 1268insert_eqs([OldVar/Equivs|Rest],Depth,Last,NewLast,M):-
 1269	M:'$aleph_sat_vars'(OldVar,TNo,_,_),
 1270	M:'$aleph_sat_terms'(TNo,_,_,Type),
 1271	add_eqs(Equivs,Depth,Type,Last,Last1,M),
 1272	insert_eqs(Rest,Depth,Last1,NewLast,M).
 1273
 1274add_eqs([],_,_,L,L,_M).
 1275add_eqs([V1|Rest],Depth,Type,Last,NewLast,M):-
 1276	add_eqs(Rest,Depth,V1,Type,Last,Last1,M),
 1277	add_eqs(Rest,Depth,Type,Last1,NewLast,M).
 1278
 1279add_eqs([],_,_,_,L,L,_M).
 1280add_eqs([Var2|Rest],Depth,Var1,Type,Last,NewLast,M):-
 1281	(Depth = 0 -> 
 1282		add_lit(Last,false,(Var1=Var2),[1/Type],[2/Type],[Var1],[Var2],Last1,M);
 1283		add_lit(Last,false,(Var1=Var2),[1/Type,2/Type],[],[Var1,Var2],[],Last1),M),
 1284	add_eqs(Rest,Depth,Var1,Type,Last1,NewLast,M).
 1285	
 1286
 1287
 1288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 1289% utilities for updating mappings between terms and variables
 1290
 1291% integrate terms specified by a list of arguments
 1292% integrating a term means:
 1293%	updating 2 databases: terms and vars
 1294%	terms contains the term along with a term-id
 1295%	vars contains a var-id <-> term-id mapping
 1296% var and term-ids are integers
 1297integrate_args(_,_,[],_M):-!.
 1298integrate_args(Depth,Literal,[Pos/Type|T],M):-
 1299        tparg(Pos,Literal,Term),
 1300        integrate_term(Depth,Term/Type,M),
 1301	(retract(M:'$aleph_sat_terms'(TNo,Depth,Term,unknown)) ->
 1302		asserta(M:'$aleph_sat_terms'(TNo,Depth,Term,Type));
 1303		true),
 1304        integrate_args(Depth,Literal,T,M).
 1305
 1306
 1307% integrate a term
 1308integrate_term(Depth,Term/Type,M):-
 1309        M:'$aleph_sat_terms'(TNo,Depth,Term,Type),
 1310        M:'$aleph_sat_vars'(_,TNo,_,[_|_]), !.
 1311integrate_term(Depth,Term/Type,M):-
 1312        M:'$aleph_sat_terms'(TNo,Depth1,Term,Type),
 1313        (Type = unknown ; M:'$aleph_sat_vars'(_,TNo,_,[])), !,
 1314	(Depth1 = unknown ->
 1315        	retract(M:'$aleph_sat_terms'(TNo,Depth1,Term,Type)),
 1316		asserta(M:'$aleph_sat_terms'(TNo,Depth,Term,Type));
 1317		true).
 1318integrate_term(_,Term/Type,M):-
 1319        M:'$aleph_sat_terms'(_,_,Term,Type),
 1320        Type \= unknown,
 1321        !.
 1322integrate_term(Depth,Term/Type,M):-
 1323	retract(M:'$aleph_sat'(lastterm,Num)),
 1324	retract(M:'$aleph_sat'(lastvar,Var0)),
 1325	TNo is Num + 1,
 1326	Var is Var0 + 1,
 1327	asserta(M:'$aleph_sat'(lastterm,TNo)),
 1328	asserta(M:'$aleph_sat'(lastvar,Var)),
 1329	asserta(M:'$aleph_sat_vars'(Var,TNo,[],[])),
 1330	asserta(M:'$aleph_sat_terms'(TNo,Depth,Term,Type)).
 1331
 1332
 1333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 1334
 1335% split_args(+Lit,?Mode,-Input,-Output,-Constants)
 1336%       return term-places and types of +,-, and # args in Lit
 1337%       by finding a matching mode declaration if Mode is given
 1338%       otherwise first mode that matches is used
 1339split_args(Lit,Mode,Input,Output,Constants,M):-
 1340        functor(Lit,Psym,Arity),
 1341		find_mode(mode,Psym/Arity,Mode,M),
 1342        functor(Template,Psym,Arity),
 1343	copy_modeterms(Mode,Template,Arity),
 1344	Template = Lit,
 1345	tp(Mode,TPList),
 1346	split_tp(TPList,Input,Output,Constants).
 1347
 1348% split_tp(+TPList,-Input,-Output,-Constants)
 1349%	split term-place/type list into +,-,#
 1350split_tp([],[],[],[]).
 1351split_tp([(+Type)/Place|TP],[Place/Type|Input],Output,Constants):-
 1352	!,
 1353	split_tp(TP,Input,Output,Constants).
 1354split_tp([(-Type)/Place|TP],Input,[Place/Type|Output],Constants):-
 1355	!,
 1356	split_tp(TP,Input,Output,Constants).
 1357split_tp([(#Type)/Place|TP],Input,Output,[Place/Type|Constants]):-
 1358	!,
 1359	split_tp(TP,Input,Output,Constants).
 1360split_tp([_|TP],Input,Output,Constants):-
 1361	split_tp(TP,Input,Output,Constants).
 1362
 1363% tp(+Literal,-TPList)
 1364%	return terms and places in Literal
 1365tp(Literal,TPList):-
 1366	functor(Literal,_,Arity),
 1367	tp_list(Literal,Arity,[],[],TPList).
 1368
 1369tp_list(_,0,_,L,L):- !.
 1370tp_list(Term,Pos,PlaceList,TpSoFar,TpList):-
 1371	arg(Pos,Term,Arg),
 1372	aleph_append([Pos],PlaceList,Places),
 1373	unwrap_term(Arg,Places,[Arg/Places|TpSoFar],L1),
 1374	Pos1 is Pos - 1,
 1375	tp_list(Term,Pos1,PlaceList,L1,TpList).
 1376
 1377unwrap_term(Term,_,L,L):-
 1378	var(Term), !.
 1379unwrap_term(Term,Place,TpSoFar,TpList):-
 1380	functor(Term,_,Arity),
 1381	tp_list(Term,Arity,Place,TpSoFar,TpList).
 1382
 1383get_determs(PSym/Arity,L,M):-
 1384	findall(Pred,M:'$aleph_global'(determination,determination(PSym/Arity,Pred)),L).
 1385
 1386get_modes(PSym/Arity,L,M):-
 1387	functor(Lit,PSym,Arity),
 1388	findall(Lit,M:'$aleph_global'(mode,mode(_,Lit)),L).
 1389
 1390
 1391%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 1392% S E A R C H
 1393
 1394% basic search engine for single clause search
 1395search(S,Nodes,M):-
 1396	arg(36,S,Time),
 1397	Inf is inf,
 1398	Time =\= Inf, 
 1399	SearchTime is integer(Time),
 1400	SearchTime > 0, !,
 1401	catch(time_bound_call(SearchTime,searchlimit,graphsearch(S,_),M),
 1402		searchlimit,p_message('Time limit reached')),
 1403	M:'$aleph_search'(current,current(_,Nodes,_)).
 1404search(S,Nodes,M):-
 1405	graphsearch(S,Nodes,M).
 1406
 1407% basic search engine for theory-based search
 1408tsearch(S,Nodes,M):-
 1409        arg(36,S,Time),
 1410	Inf is inf,
 1411        Time =\= Inf,
 1412        SearchTime is integer(Time),
 1413        SearchTime > 0, !,
 1414	alarm(SearchTime,throw(searchlimit),Id),
 1415        catch(theorysearch(S,Nodes,M),searchlimit,p_message('Time limit reached')),
 1416	remove_alarm(Id).
 1417tsearch(S,Nodes,M):-
 1418        theorysearch(S,Nodes,M).
 1419
 1420graphsearch(S,Nodes,M):-
 1421	next_node(_,M), !,
 1422        arg(3,S,RefineOp),
 1423	arg(23,S,LazyPreds),
 1424        repeat,
 1425	next_node(NodeRef,M),
 1426        once(retract(M:'$aleph_search'(current,current(LastE,Last,BestSoFar)))),
 1427        expand(RefineOp,S,NodeRef,Node,Path,MinLength,Succ,PosCover,NegCover,OVars,
 1428		PrefixClause,PrefixTV,PrefixLength,M),
 1429        ((LazyPreds = []; RefineOp \= false)  -> Succ1 = Succ;
 1430		lazy_evaluate(Succ,LazyPreds,Path,PosCover,NegCover,Succ1,M)),
 1431	NextE is LastE + 1,
 1432        get_gains(S,Last,BestSoFar,Path,PrefixClause,PrefixTV,PrefixLength,
 1433                MinLength,Succ1,PosCover,NegCover,OVars,NextE,Last0,NextBest0,M),
 1434	(RefineOp = false ->
 1435        	get_sibgains(S,Node,Last0,NextBest0,Path,PrefixClause,
 1436			PrefixTV,PrefixLength,MinLength,PosCover,NegCover,
 1437			OVars,NextE,Last1,NextBest,M);
 1438		Last1 = Last0, NextBest = NextBest0),
 1439        asserta(M:'$aleph_search'(current,current(NextE,Last1,NextBest))),
 1440        NextL is Last + 1,
 1441        asserta(M:'$aleph_search_expansion'(NextE,Node,NextL,Last1)),
 1442        (discontinue_search(S,NextBest,Last1,M) ->
 1443                M:'$aleph_search'(current,current(_,Nodes,_));
 1444                prune_open(S,BestSoFar,NextBest,M),
 1445                get_nextbest(S,Next,M),
 1446		Next = none,
 1447		M:'$aleph_search'(current,current(_,Nodes,_))),
 1448	!.
 1449graphsearch(_,Nodes,M):-
 1450	M:'$aleph_search'(current,current(_,Nodes,_)).
 1451
 1452theorysearch(S,Nodes,M):-
 1453        next_node(_,M), !,
 1454        M:'$aleph_global'(atoms,atoms(pos,Pos)),
 1455        M:'$aleph_global'(atoms,atoms(neg,Neg)),
 1456        interval_count(Pos,P,M),
 1457        interval_count(Neg,N,M),
 1458        repeat,
 1459        next_node(NodeRef,M),
 1460	M:'$aleph_search_node'(NodeRef,Theory,_,_,_,_,_,_),
 1461        once(retract(M:'$aleph_search'(current,current(_,Last,BestSoFar)))),
 1462        get_theory_gain(S,Last,BestSoFar,Theory,Pos,Neg,P,N,NextBest,Last1,M),
 1463        asserta(M:'$aleph_search'(current,current(0,Last1,NextBest))),
 1464        (discontinue_search(S,NextBest,Last1,M) ->
 1465                M:'$aleph_search'(current,current(_,Nodes,_));
 1466                prune_open(S,BestSoFar,NextBest,M),
 1467                get_nextbest(S,Next,M),
 1468                Next = none,
 1469                M:'$aleph_search'(current,current(_,Nodes,_))),
 1470	 !.
 1471theorysearch(_,Nodes,M):-
 1472        M:'$aleph_search'(current,current(_,Nodes,_)).
 1473
 1474next_node(NodeRef,M):-
 1475	once(M:'$aleph_search'(nextnode,NodeRef)), !.
 1476
 1477get_search_settings(S,M):-
 1478        functor(S,set,47),
 1479	setting(nodes,MaxNodes,M), arg(1,S,MaxNodes),
 1480	setting(explore,Explore,M), arg(2,S,Explore),
 1481	setting(refineop,RefineOp,M), arg(3,S,RefineOp),
 1482	setting(searchstrat,SearchStrat,M), setting(evalfn,EvalFn,M),
 1483	arg(4,S,SearchStrat/EvalFn),
 1484	(setting(greedy,Greedy,M)-> arg(5,S,Greedy); arg(5,S,false)),
 1485	setting(verbosity,Verbose,M), arg(6,S,Verbose),
 1486	setting(clauselength,CLength,M), arg(7,S,CLength),
 1487	setting(caching,Cache,M), arg(8,S,Cache),
 1488	(setting(prune_defs,Prune,M)-> arg(9,S,Prune); arg(9,S,false)),
 1489	setting(lazy_on_cost,LCost,M), arg(10,S,LCost),
 1490	setting(lazy_on_contradiction,LContra,M), arg(11,S,LContra),
 1491	setting(lazy_negs,LNegs,M), arg(12,S,LNegs),
 1492	setting(minpos,MinPos,M), arg(13,S,MinPos),
 1493	setting(depth,Depth,M), arg(14,S,Depth),
 1494	setting(cache_clauselength,CCLim,M), arg(15,S,CCLim),
 1495        (M:'$aleph_global'(size,size(pos,PSize))-> arg(16,S,PSize); arg(16,S,0)),
 1496	setting(noise,Noise,M), arg(17,S,Noise),
 1497	setting(minacc,MinAcc,M), arg(18,S,MinAcc),
 1498	setting(minscore,MinScore,M), arg(19,S,MinScore),
 1499        (M:'$aleph_global'(size,size(rand,RSize))-> arg(20,S,RSize); arg(20,S,0)),
 1500	setting(mingain,MinGain,M), arg(21,S,MinGain),
 1501	setting(search,Search,M), arg(22,S,Search),
 1502	findall(PN/PA,M:'$aleph_global'(lazy_evaluate,lazy_evaluate(PN/PA)),LazyPreds),
 1503	arg(23,S,LazyPreds),
 1504        (M:'$aleph_global'(size,size(neg,NSize))-> arg(24,S,NSize); arg(24,S,0)),
 1505	setting(openlist,OSize,M), arg(25,S,OSize),
 1506        setting(check_redundant,RCheck,M), arg(26,S,RCheck),
 1507        (M:'$aleph_sat'(eq,Eq) -> arg(27,S,Eq); arg(27,S,false)),
 1508        (M:'$aleph_sat'(hovars,HOVars) -> arg(28,S,HOVars); arg(28,S,_HOVars)),
 1509	setting(prooftime,PTime,M), arg(29,S,PTime),
 1510	setting(construct_bottom,CBott,M), arg(30,S,CBott),
 1511	(get_ovars1(false,1,HIVars,M) ->  arg(31,S,HIVars); arg(31,S,[])),
 1512	setting(language,Lang,M), arg(32,S,Lang),
 1513	setting(splitvars,Split,M), arg(33,S,Split),
 1514	setting(proof_strategy,Proof,M), arg(34,S,Proof),
 1515	setting(portray_search,VSearch,M), arg(35,S,VSearch),
 1516	setting(searchtime,Time,M), arg(36,S,Time),
 1517	setting(optimise_clauses,Optim,M), arg(37,S,Optim),
 1518	setting(newvars,NewV,M), arg(38,S,NewV),
 1519	(setting(rls_type,RlsType,M) -> arg(39,S,RlsType);arg(39,S,false,M)),
 1520	setting(minposfrac,MinPosFrac,M), arg(40,S,MinPosFrac),
 1521	(setting(recursion,_Recursion,M) -> true; _Recursion = false),
 1522	prolog_type(Prolog), arg(41,S,Prolog),
 1523	setting(interactive,Interactive,M), arg(42,S,Interactive),
 1524	setting(lookahead,LookAhead,M), arg(43,S,LookAhead),
 1525	(setting(construct_features,Features,M)-> arg(44,S,Features); arg(44,S,false)),
 1526	setting(max_features,FMax,M), arg(45,S,FMax),
 1527	setting(subsample,SS,M), arg(46,S,SS),
 1528	setting(subsamplesize,SSize,M), arg(47,S,SSize).
 1529
 1530% stop search from proceeding if certain
 1531% conditions are reached. These are:
 1532%	. minacc and minpos values reached in rrr search
 1533%	. best hypothesis has accuracy 1.0 if evalfn=accuracy
 1534%	. best hypothesis covers all positive examples
 1535discontinue_search(S,[P,_,_,F|_]/_,_,_M):-
 1536	arg(39,S,RlsType),
 1537	RlsType = rrr, 
 1538	arg(13,S,MinPos),
 1539	P >= MinPos,
 1540	arg(19,S,MinScore),
 1541	F >= MinScore, !.
 1542discontinue_search(S,_,Nodes,_M):-
 1543        arg(1,S,MaxNodes),
 1544        Nodes >= MaxNodes, !,
 1545	p_message('node limit reached').
 1546discontinue_search(S,_,_,M):-
 1547        arg(44,S,Features),
 1548	Features = true,
 1549	arg(45,S,FMax),
 1550	M:'$aleph_search'(last_good,LastGood),
 1551        LastGood >= FMax, !,
 1552	p_message('feature limit reached').
 1553discontinue_search(S,[_,_,_,F|_]/_,_,_M):-
 1554        arg(4,S,_/Evalfn),
 1555	Evalfn = accuracy,
 1556	F = 1.0, !.
 1557discontinue_search(S,Best,_,_M):-
 1558	arg(2,S,Explore),
 1559	Explore = false,
 1560        arg(4,S,_/Evalfn),
 1561	Evalfn \= user,
 1562	Evalfn \= posonly,
 1563	arg(22,S,Search),
 1564	Search \= ic,
 1565	Best = [P|_]/_,
 1566	arg(16,S,P).
 1567
 1568update_max_head_count(N,0,M):-
 1569	retractall(M:'$aleph_local'(max_head_count,_)),
 1570	asserta(M:'$aleph_local'(max_head_count,N)), !.
 1571update_max_head_count(Count,Last,M):-
 1572	M:'$aleph_search_node'(Last,LitNum,_,_,PosCover,_,_,_), !,
 1573	asserta(M:'$aleph_local'(head_lit,LitNum)),
 1574	interval_count(PosCover,N),
 1575	Next is Last - 1,
 1576	(N > Count -> update_max_head_count(N,Next,M);
 1577		update_max_head_count(Count,Next,M)).
 1578update_max_head_count(Count,Last,M):-
 1579	Next is Last - 1,
 1580	update_max_head_count(Count,Next,M).
 1581
 1582expand(false,S,NodeRef,NodeRef,Path1,Length,Descendents,PosCover,NegCover,OVars,C,TV,CL,M):-
 1583	!,
 1584        M:'$aleph_search_node'(NodeRef,LitNum,Path,Length/_,PCover,NCover,OVars,_),
 1585	arg(46,S,SSample),
 1586	(SSample = false -> PosCover = PCover, NegCover = NCover;
 1587		get_sample_cover(S,PosCover,NegCover,M)),
 1588        aleph_append([LitNum],Path,Path1),
 1589	get_pclause(Path1,[],C,TV,CL,_,M),
 1590        M:'$aleph_sat_litinfo'(LitNum,_,_,_,_,Dependents),
 1591        intersect1(Dependents,Path1,_,Succ),
 1592        check_parents(Succ,OVars,Descendents,_,M).
 1593expand(_,S,NodeRef,NodeRef,Path1,Length,[_],PosCover,NegCover,OVars,_,_,_,M):-
 1594        retract(M:'$aleph_search_node'(NodeRef,_,Path1,Length/_,_,_,OVars,_)),
 1595	get_sample_cover(S,PosCover,NegCover,M).
 1596
 1597get_sample_cover(S,PosCover,NegCover,M):-
 1598        arg(5,S,Greedy),
 1599        (Greedy = true ->
 1600                M:'$aleph_global'(atoms_left,atoms_left(pos,PCover));
 1601                arg(16,S,PSize),
 1602                PCover = [1-PSize]),
 1603        arg(4,S,_/Evalfn),
 1604	(Evalfn = posonly -> 
 1605                M:'$aleph_global'(atoms_left,atoms_left(rand,NCover));
 1606                arg(24,S,NSize),
 1607                NCover = [1-NSize]),
 1608	arg(46,S,SSample),
 1609	(SSample = false -> PosCover = PCover, NegCover = NCover;
 1610		arg(47,S,SampleSize),
 1611		interval_sample(SampleSize,PCover,PosCover,M),
 1612		interval_sample(SampleSize,NCover,NegCover,M)).
 1613
 1614get_ovars([],_,V,V,_M).
 1615get_ovars([LitNum|Lits],K,VarsSoFar,Vars,M):-
 1616	get_ovars1(K,LitNum,OVars,M),
 1617	aleph_append(VarsSoFar,OVars,Vars1),
 1618	get_ovars(Lits,K,Vars1,Vars,M).
 1619
 1620get_ovars1(false,LitNum,OVars,M):-
 1621	M:'$aleph_sat_ovars'(LitNum,OVars), !.
 1622get_ovars1(false,LitNum,OVars,M):-
 1623	!,
 1624	M:'$aleph_sat_litinfo'(LitNum,_,Atom,_,O,_),
 1625	get_vars(Atom,O,OVars).
 1626get_ovars1(K,LitNum,OVars,M):-
 1627	M:'$aleph_sat_ovars'(LitNum,K,OVars), !.
 1628get_ovars1(K,LitNum,OVars,M):-
 1629	M:'$aleph_sat_litinfo'(LitNum,K,_,Atom,_,O,_),
 1630	get_vars(Atom,O,OVars).
 1631
 1632% get set of vars at term-places specified
 1633get_vars(not(Literal),Args,Vars):-
 1634	!,
 1635	get_vars(Literal,Args,Vars).
 1636get_vars(_,[],[]).
 1637get_vars(Literal,[ArgNo|Args],Vars):-
 1638	(ArgNo = Pos/_ -> true; Pos = ArgNo),
 1639	tparg(Pos,Literal,Term),
 1640	get_vars_in_term([Term],TV1),
 1641	get_vars(Literal,Args,TV2),
 1642	update_list(TV2,TV1,Vars).
 1643
 1644get_vars_in_term([],[]).
 1645get_vars_in_term([Var|Terms],[Var|TVars]):-
 1646	integer(Var), !,
 1647	get_vars_in_term(Terms,TVars).
 1648get_vars_in_term([Term|Terms],TVars):-
 1649	Term =.. [_|Terms1],
 1650	get_vars_in_term(Terms1,TV1),
 1651	get_vars_in_term(Terms,TV2),
 1652	update_list(TV2,TV1,TVars).
 1653
 1654% get terms at term-places specified
 1655% need not be variables
 1656get_argterms(not(Literal),Args,TermsSoFar,Terms):-
 1657        !,
 1658        get_argterms(Literal,Args,TermsSoFar,Terms).
 1659get_argterms(_,[],Terms,Terms).
 1660get_argterms(Literal,[ArgNo|Args],TermsSoFar,Terms):-
 1661	(ArgNo = Pos/_ -> true; Pos = ArgNo),
 1662        tparg(Pos,Literal,Term),
 1663        update(TermsSoFar,Term,T1),
 1664        get_argterms(Literal,Args,T1,Terms).
 1665
 1666% get list of terms at arg positions specified
 1667get_args(not(Literal),Args,TermsSoFar,Terms):-
 1668        !,
 1669        get_args(Literal,Args,TermsSoFar,Terms).
 1670get_args(_,[],Terms,Terms).
 1671get_args(Literal,[ArgNo|Args],TermsSoFar,Terms):-
 1672	(ArgNo = Pos/_ -> true; Pos = ArgNo),
 1673        tparg(Pos,Literal,Term),
 1674        get_args(Literal,Args,[Term|TermsSoFar],Terms).
 1675
 1676
 1677get_ivars([],_,V,V,_M).
 1678get_ivars([LitNum|Lits],K,VarsSoFar,Vars,M):-
 1679	get_ivars1(K,LitNum,IVars,M),
 1680	aleph_append(VarsSoFar,IVars,Vars1),
 1681	get_ivars(Lits,K,Vars1,Vars,M).
 1682
 1683get_ivars1(false,LitNum,IVars,M):-
 1684	M:'$aleph_sat_ivars'(LitNum,IVars), !.
 1685get_ivars1(false,LitNum,IVars,M):-
 1686	!,
 1687	M:'$aleph_sat_litinfo'(LitNum,_,Atom,I,_,_),
 1688	get_vars(Atom,I,IVars).
 1689get_ivars1(K,LitNum,IVars,M):-
 1690	M:'$aleph_sat_ivars'(LitNum,K,IVars), !.
 1691get_ivars1(K,LitNum,IVars,M):-
 1692	M:'$aleph_sat_litinfo'(LitNum,K,_,Atom,I,_,_),
 1693	get_vars(Atom,I,IVars).
 1694
 1695check_parents([],_,[],[],_M).
 1696check_parents([LitNum|Lits],OutputVars,[LitNum|DLits],Rest,M):-
 1697	get_ivars1(false,LitNum,IVars,M),
 1698	aleph_subset1(IVars,OutputVars), !,
 1699	check_parents(Lits,OutputVars,DLits,Rest,M).
 1700check_parents([LitNum|Lits],OutputVars,DLits,[LitNum|Rest],M):-
 1701	check_parents(Lits,OutputVars,DLits,Rest,M), !.
 1702
 1703get_gains(S,Last,Best,_,_,_,_,_,_,_,_,_,_,Last,Best,M):-
 1704        discontinue_search(S,Best,Last,M), !.
 1705get_gains(_,Last,Best,_,_,_,_,_,[],_,_,_,_,Last,Best,_M):- !.
 1706get_gains(S,Last,Best,Path,C,TV,L,Min,[L1|Succ],Pos,Neg,OVars,E,Last1,NextBest,M):-
 1707        get_gain(S,upper,Last,Best,Path,C,TV,L,Min,L1,Pos,Neg,OVars,E,Best1,Node1,M), !,
 1708        get_gains(S,Node1,Best1,Path,C,TV,L,Min,Succ,Pos,Neg,OVars,E,Last1,NextBest,M).
 1709get_gains(S,Last,BestSoFar,Path,C,TV,L,Min,[_|Succ],Pos,Neg,OVars,E,Last1,NextBest,M):-
 1710        get_gains(S,Last,BestSoFar,Path,C,TV,L,Min,Succ,Pos,Neg,OVars,E,Last1,NextBest,M),
 1711        !.
 1712
 1713get_sibgains(S,Node,Last,Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,Last1,NextBest,M):-
 1714        M:'$aleph_search_node'(Node,LitNum,_,_,_,_,_,OldE),
 1715        M:'$aleph_search_expansion'(OldE,_,_,LastSib),
 1716        M:'$aleph_sat_litinfo'(LitNum,_,_,_,_,Desc),
 1717        Node1 is Node + 1,
 1718        arg(31,S,HIVars),
 1719        aleph_delete_list(HIVars,OVars,LVars),
 1720        get_sibgain(S,LVars,LitNum,Desc,Node1,LastSib,Last,
 1721                Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,NextBest,Last1,M), !.
 1722
 1723get_sibgain(S,_,_,_,Node,Node1,Last,Best,_,_,_,_,_,_,_,_,_,Best,Last,M):-
 1724        (Node > Node1;
 1725        discontinue_search(S,Best,Last,M)), !.
 1726get_sibgain(S,LVars,LitNum,Desc,Node,LastSib,Last,Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,LBest,LNode,M):-
 1727        arg(23,S,Lazy),
 1728        get_sibpncover(Lazy,Node,Desc,Pos,Neg,Sib1,PC,NC,M),
 1729        lazy_evaluate([Sib1],Lazy,Path,PC,NC,[Sib],M),
 1730        get_ivars1(false,Sib,SibIVars,M),
 1731        (intersects(SibIVars,LVars) -> Flag = upper;
 1732                get_ovars1(false,Sib,SibOVars,M),
 1733                (intersects(SibOVars,LVars) -> Flag = upper; Flag = exact)),
 1734        get_gain(S,Flag,Last,Best,Path,C,TV,L,Min,Sib,PC,NC,OVars,E,Best1,Node1,M), !,
 1735        NextNode is Node + 1,
 1736        get_sibgain(S,LVars,LitNum,Desc,NextNode,LastSib,Node1,Best1,Path,C,TV,L,
 1737                        Min,Pos,Neg,OVars,E,LBest,LNode,M), !.
 1738get_sibgain(S,LVars,LitNum,Desc,Node,LastSib,Last,Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,Best1,Node1,M):-
 1739	NextNode is Node + 1,
 1740        get_sibgain(S,LVars,LitNum,Desc,NextNode,LastSib,Last,Best,Path,C,TV,L,
 1741                        Min,Pos,Neg,OVars,E,Best1,Node1,M), !.
 1742
 1743
 1744get_sibgain(S,LVars,LitNum,Node,LastSib,Last,Best,Path,C,TV,L,Min,Pos,Neg,OVars,E,Best1,Node1,M):-
 1745	NextNode is Node + 1,
 1746	get_sibgain(S,LVars,LitNum,NextNode,LastSib,Last,Best,Path,C,TV,L,Min,Pos,Neg,
 1747			OVars,E,Best1,Node1,M), !.
 1748
 1749get_sibpncover(Lazy,NodeNum,Desc,Pos,Neg,Sib,PC,NC,M):-
 1750        M:'$aleph_search_node'(NodeNum,Sib,_,_,Pos1,Neg1,_,_),
 1751        M:'$aleph_sat_litinfo'(Sib,_,Atom,_,_,_),
 1752        \+(aleph_member1(Sib,Desc)),
 1753        functor(Atom,Name,Arity),
 1754        (aleph_member1(Name/Arity,Lazy) ->
 1755                PC = Pos, NC = Neg;
 1756                calc_intersection(Pos,Pos1,PC),
 1757                calc_intersection(Neg,Neg1,NC)).
 1758
 1759% in some cases, it is possible to simply use the intersection of
 1760% covers cached. The conditions under which this is possible was developed
 1761% in discussions with James Cussens
 1762calc_intersection(A1/[B1-L1],A2/[B2-L2],A/[B-L]):-
 1763	!,
 1764	intervals_intersection(A1,A2,A),
 1765	B3 is max(B1,B2),
 1766	(intervals_intersects(A1,[B2-L2],X3-_) -> true; X3 = B3),
 1767	(intervals_intersects(A2,[B1-L1],X4-_) -> true; X4 = B3),
 1768	B4 is min(X3,B3),
 1769	B is min(X4,B4),
 1770	L is max(L1,L2).
 1771calc_intersection(A1/_,A2,A):-
 1772	!,
 1773	intervals_intersection(A1,A2,A).
 1774calc_intersection(A1,A2/_,A):-
 1775	!,
 1776	intervals_intersection(A1,A2,A).
 1777calc_intersection(A1,A2,A):-
 1778	intervals_intersection(A1,A2,A).
 1779
 1780get_gain(S,_,Last,Best,Path,_,_,_,MinLength,_,Pos,Neg,OVars,E,Best1,NewLast,M):-
 1781        arg(3,S,RefineOp),
 1782        RefineOp \= false , !,
 1783	get_refine_gain(S,Last,Best,Path,MinLength,Pos,Neg,OVars,E,Best1,NewLast,M).
 1784get_gain(S,Flag,Last,Best/Node,Path,C,TV,Len1,MinLen,L1,Pos,Neg,OVars,E,Best1,Last1,M):-
 1785	arg(26,S,RCheck),
 1786	arg(33,S,SplitVars),
 1787	retractall(M:'$aleph_search'(covers,_)),
 1788	retractall(M:'$aleph_search'(coversn,_)),
 1789        get_pclause([L1],TV,Lit1,_,Len2,LastD,M),
 1790	split_ok(SplitVars,C,Lit1), !,
 1791        extend_clause(C,Lit1,Clause),
 1792	(RCheck = true ->
 1793		(redundant(Clause,Lit1,M) -> fail; true);
 1794		true),
 1795        CLen is Len1 + Len2,
 1796        length_ok(S,MinLen,CLen,LastD,EMin,ELength),
 1797	% arg(41,S,Prolog),
 1798        split_clause(Clause,Head,Body),
 1799        % (Prolog = yap ->
 1800		% assertz(M:'$aleph_search'(pclause,pclause(Head,Body)),DbRef);
 1801		% assertz(M:'$aleph_search'(pclause,pclause(Head,Body)))),
 1802	assertz(M:'$aleph_search'(pclause,pclause(Head,Body))),
 1803        arg(6,S,Verbosity),
 1804        (Verbosity >= 1 ->
 1805		pp_dclause(Clause,M);
 1806		true),
 1807        get_gain1(S,Flag,Clause,CLen,EMin/ELength,Last,Best/Node,
 1808                        Path,L1,Pos,Neg,OVars,E,Best1,M),
 1809        % (Prolog = yap ->
 1810		% erase(DbRef);
 1811		% retractall(M:'$aleph_search'(pclause,_))),
 1812	retractall(M:'$aleph_search'(pclause,_)),
 1813        Last1 is Last + 1.
 1814get_gain(_,_,Last,Best,_,_,_,_,_,_,_,_,_,_,Best,Last,_M).
 1815
 1816get_refine_gain(S,Last,Best/Node,Path,MinLength,Pos,Neg,OVars,E,Best1,NewLast,M):-
 1817        arg(3,S,RefineOp),
 1818	RefineOp = rls,
 1819	refine_prelims(Best/Node,Last,M),
 1820	rls_refine(clauses,Path,Path1,M),
 1821	get_refine_gain1(S,Path1,MinLength,Pos,Neg,OVars,E,Best1,NewLast,M),
 1822	!.
 1823get_refine_gain(S,Last,Best/Node,Path,MinLength,Pos,Neg,OVars,E,Best1,NewLast,M):-
 1824        arg(3,S,RefineOp),
 1825	RefineOp \= rls,
 1826	refine_prelims(Best/Node,Last,M),
 1827	Path = CL-[Example,Type,_,Clause],
 1828	arg(30,S,ConstructBottom),
 1829        arg(43,S,LookAhead),
 1830        get_user_refinement(RefineOp,LookAhead,Clause,R,_,M),
 1831	match_bot(ConstructBottom,R,R1,LitNums,M),
 1832	Path1 = CL-[Example,Type,LitNums,R1],
 1833	get_refine_gain1(S,Path1,MinLength,Pos,Neg,OVars,E,Best1,NewLast,M),
 1834	!.
 1835get_refine_gain(_,_,_,_,_,_,_,_,_,Best,Last,M):-
 1836	retract(M:'$aleph_search'(best_refinement,best_refinement(Best))),
 1837	retract(M:'$aleph_search'(last_refinement,last_refinement(Last))).
 1838
 1839get_theory_gain(S,Last,BestSoFar,T0,Pos,Neg,P,N,Best1,NewLast,M):-
 1840	refine_prelims(BestSoFar,Last,M),
 1841	arg(3,S,RefineOp),
 1842	(RefineOp = rls -> rls_refine(theories,T0,T1,M); fail),
 1843	arg(23,S,LazyPreds),
 1844	(LazyPreds = [] -> Theory = T1;
 1845		lazy_evaluate_theory(T1,LazyPreds,Pos,Neg,Theory,M)),
 1846	retract(M:'$aleph_search'(best_refinement,best_refinement(OldBest))),
 1847	retract(M:'$aleph_search'(last_refinement,last_refinement(OldLast))),
 1848        arg(6,S,Verbosity),
 1849        (Verbosity >= 1 ->
 1850                p_message('new refinement'),
 1851                pp_dclauses(Theory,M);
 1852        true),
 1853	record_pclauses(Theory,M),
 1854	get_theory_gain1(S,Theory,OldLast,OldBest,Pos,Neg,P,N,Best1,M),
 1855	retractall(M:'$aleph_search'(pclause,_)),
 1856        NewLast is OldLast + 1,
 1857	asserta(M:'$aleph_search'(last_refinement,last_refinement(NewLast))),
 1858        asserta(M:'$aleph_search'(best_refinement,best_refinement(Best1))),
 1859	(discontinue_search(S,Best1,NewLast,M) ->
 1860		retract(M:'$aleph_search'(last_refinement,last_refinement(_))),
 1861		retract(M:'$aleph_search'(best_refinement,best_refinement(_)));
 1862		fail),
 1863	!.
 1864get_theory_gain(_,_,_,_,_,_,_,_,Best,Last,M):-
 1865	M:'$aleph_search'(best_refinement,best_refinement(Best)),
 1866	M:'$aleph_search'(last_refinement,last_refinement(Last)).
 1867
 1868refine_prelims(Best,Last,M):-
 1869	retractall(M:'$aleph_search'(last_refinement,_)),
 1870	retractall(M:'$aleph_search'(best_refinement,_)),
 1871        asserta(M:'$aleph_search'(best_refinement,best_refinement(Best))),
 1872	asserta(M:'$aleph_search'(last_refinement,last_refinement(Last))).
 1873
 1874get_refine_gain1(S,Path,MinLength,Pos,Neg,OVars,E,Best1,NewLast,M):-
 1875        arg(23,S,LazyPreds),
 1876	Path = CL-[Example,Type,Ids,Refine],
 1877	(LazyPreds = [] -> Ids1 = Ids, Clause = Refine;
 1878		lazy_evaluate_refinement(Ids,Refine,LazyPreds,Pos,Neg,Ids1,Clause,M)),
 1879	retractall(M:'$aleph_search'(covers,_)),
 1880	retractall(M:'$aleph_search'(coversn,_)),
 1881	Path1 = CL-[Example,Type,Ids1,Clause],
 1882	split_clause(Clause,Head,Body),
 1883	nlits(Body,CLength0),
 1884	CLength is CLength0 + 1,
 1885	length_ok(S,MinLength,CLength,0,EMin,ELength),
 1886	arg(41,S,Prolog),
 1887	split_clause(Clause,Head,Body),
 1888	(Prolog = yap ->
 1889		assertz(M:'$aleph_search'(pclause,pclause(Head,Body)),DbRef);
 1890		assertz(M:'$aleph_search'(pclause,pclause(Head,Body)))),
 1891	retract(M:'$aleph_search'(best_refinement,best_refinement(OldBest))),
 1892	retract(M:'$aleph_search'(last_refinement,last_refinement(OldLast))),
 1893        arg(6,S,Verbosity),
 1894        (Verbosity >= 1 ->
 1895		p_message('new refinement'),
 1896		pp_dclause(Clause,M);
 1897	true),
 1898	once(get_gain1(S,upper,Clause,CLength,EMin/ELength,OldLast,OldBest,
 1899		Path1,[],Pos,Neg,OVars,E,Best1,M)),
 1900	(Prolog = yap ->
 1901		erase(DbRef);
 1902		retractall(M:'$aleph_search'(pclause,_))),
 1903	NewLast is OldLast + 1,
 1904	asserta(M:'$aleph_search'(last_refinement,last_refinement(NewLast))),
 1905        asserta(M:'$aleph_search'(best_refinement,best_refinement(Best1))),
 1906	(discontinue_search(S,Best1,NewLast,M) ->
 1907		retract(M:'$aleph_search'(last_refinement,last_refinement(_))),
 1908		retract(M:'$aleph_search'(best_refinement,best_refinement(_)));
 1909		fail),
 1910	!.
 1911
 1912get_theory_gain1(S,Theory,Last,Best,Pos,Neg,P,N,Best1,M):-
 1913        (M:aleph_false -> p_message('constraint violated'),
 1914                Contradiction = true;
 1915                Contradiction = false),
 1916	Contradiction = false,
 1917        Node1 is Last + 1,
 1918	arg(32,S,Lang),
 1919	theory_lang_ok(Theory,Lang,M),
 1920	arg(38,S,NewVars),
 1921	theory_newvars_ok(Theory,NewVars),
 1922	arg(14,S,Depth),
 1923	arg(29,S,Time),
 1924	arg(34,S,Proof),
 1925        prove(Depth/Time/Proof,pos,(X:-X),Pos,PCvr,TP,M),
 1926        prove(Depth/Time/Proof,neg,(X:-X),Neg,NCvr,FP,M),
 1927	arg(4,S,_/Evalfn),
 1928	Correct is TP + (N - FP),
 1929	Incorrect is FP + (P - TP),
 1930	length(Theory,L),
 1931	Label = [Correct,Incorrect,L],
 1932	complete_label(Evalfn,Theory,Label,Label1,M),
 1933	get_search_keys(heuristic,Label1,SearchKeys),
 1934	arg(6,S,Verbosity),
 1935	(Verbosity >= 1 -> p_message(Correct/Incorrect); true),
 1936	asserta(M:'$aleph_search_node'(Node1,Theory,[],0,PCvr,NCvr,[],0)),
 1937	update_open_list(SearchKeys,Node1,Label1,M),
 1938	update_best_theory(S,Theory,PCvr,NCvr,Best,Label1/Node1,Best1,M), !.
 1939get_theory_gain1(_,_,_,Best,_,_,_,_,Best,_M).
 1940
 1941get_gain1(S,_,C,CL,_,Last,Best,Path,_,Pos,Neg,_,E,Best,M):-
 1942        abandon_branch(S,C,M), !,
 1943        Node1 is Last + 1,
 1944        arg(3,S,RefineOp),
 1945        arg(7,S,ClauseLength),
 1946	arg(35,S,VSearch),
 1947        (ClauseLength = CL -> true;
 1948                (RefineOp = false  ->
 1949                        asserta(M:'$aleph_search_node'(Node1,0,Path,0,Pos,Neg,[],E));
 1950			true)),
 1951	(VSearch = true ->
 1952		asserta(M:'$aleph_search'(bad,Node1)),
 1953		asserta(M:'$aleph_search_node'(Node1,C));
 1954		true).
 1955get_gain1(S,_,Clause,_,_,_,Best,_,_,_,_,_,_,Best,M):-
 1956        arg(8,S,Caching),
 1957        Caching = true,
 1958        skolemize(Clause,SHead,SBody,0,_),
 1959        M:'$aleph_search_prunecache'([SHead|SBody]), !,
 1960	arg(6,S,Verbosity),
 1961        (Verbosity >= 1 -> p_message('in prune cache'); true).
 1962get_gain1(S,Flag,C,CL,EMin/EL,Last,Best/Node,Path,L1,Pos,Neg,OVars,E,Best1,M):-
 1963	split_clause(C,Head,Body),
 1964	arg(22,S,Search),
 1965        ((Search \== ic, M:aleph_false) -> p_message('constraint violated'),
 1966                Contradiction = true;
 1967                Contradiction = false),
 1968        Node1 is Last + 1,
 1969        arg(8,S,Caching),
 1970        (Caching = true -> arg(15,S,CCLim),
 1971		get_cache_entry(CCLim,C,Entry);
 1972		Entry = false),
 1973	arg(35,S,VSearch),
 1974	(VSearch = true ->
 1975		asserta(M:'$aleph_search_node'(Node1,C));
 1976		true),
 1977        arg(3,S,RefineOp),
 1978	refinement_ok(RefineOp,Entry,M),
 1979	arg(32,S,Lang),
 1980	lang_ok((Head:-Body),Lang),
 1981	arg(38,S,NewVars),
 1982	newvars_ok((Head:-Body),NewVars),
 1983	arg(34,S,Proof),
 1984	arg(37,S,Optim),
 1985	rewrite_clause(Proof,Optim,(Head:-Body),(Head1:-Body1)),
 1986	(Search = ic ->
 1987		PCvr = [],
 1988		Label = [_,_,CL],
 1989		ccheck(S,(Head1:-Body1),NCvr,Label,M);
 1990        	prove_examples(S,Flag,Contradiction,Entry,Best,CL,EL,
 1991				(Head1:-Body1),Pos,Neg,PCvr,NCvr,Label,M)
 1992	),
 1993        arg(4,S,SearchStrat/Evalfn),
 1994	arg(40,S,MinPosFrac),
 1995	((MinPosFrac > 0.0 ; Evalfn = wracc) ->
 1996		reset_clause_prior(S,Head1,M);
 1997		true
 1998	),
 1999	arg(46,S,SSample),
 2000	(SSample = true ->
 2001		arg(47,S,SampleSize),
 2002		estimate_label(SampleSize,Label,Label0,M);
 2003		Label0 = Label),
 2004	complete_label(Evalfn,C,Label0,Label1,M),
 2005	compression_ok(Evalfn,Label1),
 2006        get_search_keys(SearchStrat,Label1,SearchKeys),
 2007        arg(6,S,Verbosity),
 2008	arg(10,S,LCost),
 2009	arg(11,S,LContra),
 2010        ((Verbosity >= 1, LContra = false, LCost = false) ->
 2011		Label = [A,B|_],
 2012		p_message(A/B);
 2013	true),
 2014        arg(7,S,ClauseLength),
 2015	(RefineOp = false ->
 2016		get_ovars1(false,L1,OVars1,M),
 2017		aleph_append(OVars1,OVars,OVars2);
 2018		true),
 2019        ((ClauseLength=CL, RefineOp = false) -> true;
 2020		(RefineOp = false ->
 2021                	asserta(M:'$aleph_search_node'(Node1,L1,Path,EMin/EL,PCvr,
 2022					NCvr,OVars2,E));
 2023                	asserta(M:'$aleph_search_node'(Node1,0,Path,EMin/EL,PCvr,
 2024					NCvr,[],E))),
 2025                	update_open_list(SearchKeys,Node1,Label1,M)),
 2026	(VSearch = true ->
 2027		asserta(M:'$aleph_search'(label,label(Node1,Label)));
 2028		true),
 2029        (((RefineOp \= false,Contradiction=false);
 2030		(arg(28,S,HOVars),clause_ok1(Contradiction,HOVars,OVars2))) ->
 2031                update_best(S,C,PCvr,NCvr,Best/Node,Label1/Node1,Best1,M);
 2032                Best1=Best/Node),
 2033	!.
 2034get_gain1(_,_,_,_,_,_,Best,_,_,_,_,_,_,Best,_M).
 2035
 2036
 2037abandon_branch(S,C,M):-
 2038        arg(9,S,PruneDefined),
 2039        PruneDefined = true,
 2040        M:prune(C), !,
 2041        arg(6,S,Verbosity),
 2042        (Verbosity >= 1 -> p_message(pruned); true).
 2043
 2044clause_ok1(false,V1,V2):-
 2045        aleph_subset1(V1,V2).
 2046
 2047% check to see if a clause is acceptable
 2048% 	unacceptable if it fails noise, minacc, or minpos settings
 2049%	unacceptable if it fails search or language constraints
 2050clause_ok(_,_,_M):-
 2051	false, !, fail.
 2052clause_ok(_,Label,M):-
 2053	extract_pos(Label,P),
 2054	extract_neg(Label,N),
 2055	Acc is P/(P+N),
 2056	setting(noise,Noise,M),
 2057	setting(minacc,MinAcc,M),
 2058	setting(minpos,MinPos,M),
 2059	(N > Noise; Acc < MinAcc; P < MinPos), !, fail.
 2060clause_ok(Clause,_,M):-
 2061	M:prune(Clause), !, fail.
 2062clause_ok(Clause,_,M):-
 2063	setting(language,Lang,M),
 2064	\+ lang_ok(Clause,Lang), !, fail.
 2065clause_ok(Clause,_,M):-
 2066	setting(newvars,NewVars,M),
 2067	\+ newvars_ok(Clause,NewVars), !, fail.
 2068clause_ok(_,_,_M).
 2069
 2070% check to see if refinement has been produced before
 2071refinement_ok(false,_,_M):- !.
 2072refinement_ok(rls,_,_M):- !.
 2073refinement_ok(_,false,_M):- !.
 2074refinement_ok(_,Entry,M):-
 2075	(check_cache(Entry,pos,_,M); check_cache(Entry,neg,_,M)), !,
 2076	p_message('redundant refinement'),
 2077	fail.
 2078refinement_ok(_,_,_M).
 2079
 2080
 2081% specialised redundancy check with equality theory
 2082% used only to check if equalities introduced by splitting vars make
 2083% literal to be added redundant
 2084split_ok(false,_,_):- !.
 2085split_ok(_,Clause,Lit):-
 2086	functor(Lit,Name,_),
 2087	Name \= '=', 
 2088	copy_term(Clause/Lit,Clause1/Lit1),
 2089	lit_redun(Lit1,Clause1), !,
 2090	p_message('redundant literal'), nl,
 2091	fail.
 2092split_ok(_,_,_).
 2093
 2094lit_redun(Lit,(Head:-Body)):-
 2095	!,
 2096	lit_redun(Lit,(Head,Body)).
 2097lit_redun(Lit,(L1,_)):-
 2098	Lit == L1, !.
 2099lit_redun(Lit,(L1,L2)):-
 2100	!,
 2101	execute_equality(L1),
 2102	lit_redun(Lit,L2).
 2103lit_redun(Lit,L):-
 2104	Lit == L.
 2105
 2106execute_equality(Lit):-
 2107	functor(Lit,'=',2), !,
 2108	Lit.
 2109execute_equality(_).
 2110	
 2111theory_lang_ok([],_).
 2112theory_lang_ok([_-[_,_,_,Clause]|T],Lang):-
 2113        lang_ok(Lang,Clause),
 2114        theory_lang_ok(Lang,T). 
 2115
 2116theory_newvars_ok([],_).
 2117theory_newvars_ok([_-[_,_,_,Clause]|T],NewV):-
 2118        newvars_ok(NewV,Clause),
 2119        theory_newvars_ok(T,NewV). 
 2120
 2121lang_ok((Head:-Body),N):-
 2122	!,
 2123	(lang_ok(N,Head,Body) -> true;
 2124		p_message('outside language bound'),
 2125		fail).
 2126
 2127lang_ok(N,_,_):- N is inf, !.
 2128lang_ok(N,Head,Body):-
 2129	get_psyms((Head,Body),PSymList),
 2130	lang_ok1(PSymList,N).
 2131
 2132newvars_ok((Head:-Body),N):-
 2133	!,
 2134	(newvars_ok(N,Head,Body) -> true;
 2135		p_message('outside newvars bound'),
 2136		fail).
 2137
 2138newvars_ok(N,_,_):- N is inf, !.
 2139newvars_ok(N,Head,Body):-
 2140	vars_in_term([Head],[],HVars),
 2141	goals_to_list(Body,BodyL),
 2142	vars_in_term(BodyL,[],BVars),
 2143        aleph_ord_subtract(BVars,HVars,NewVars),
 2144	length(NewVars,N1),
 2145	N1 =< N.
 2146
 2147get_psyms((L,B),[N/A|Syms]):-
 2148	!,
 2149	functor(L,N,A),
 2150	get_psyms(B,Syms).
 2151get_psyms(true,[]):- !.
 2152get_psyms(L,[N/A]):-
 2153	functor(L,N,A).
 2154
 2155lang_ok1([],_).
 2156lang_ok1([Pred|Preds],N):-
 2157        length(Preds,N0),
 2158        aleph_delete_all(Pred,Preds,Preds1),
 2159        length(Preds1,N1),
 2160        PredOccurs is N0 - N1 + 1,
 2161	PredOccurs =< N,
 2162	lang_ok1(Preds1,N).
 2163
 2164rewrite_clause(sld,_,_,(X:-X)):- !.
 2165rewrite_clause(restricted_sld,true,(Head:-Body),(Head1:-Body1)):- 
 2166	!,
 2167        optimise((Head:-Body),(Head1:-Body1)).
 2168rewrite_clause(_,_,Clause,Clause).
 2169
 2170record_pclauses([],_M).
 2171record_pclauses([_-[_,_,_,Clause]|T],M):-
 2172        split_clause(Clause,Head,Body),
 2173        assertz(M:'$aleph_search'(pclause,pclause(Head,Body))),
 2174        record_pclauses(T,M).
 2175
 2176% get pos/neg distribution of clause head
 2177reset_clause_prior(S,Head,M):-
 2178	arg(3,S,Refine),
 2179	Refine = false, !,
 2180	(M:'$aleph_search'(clauseprior,_) -> true;
 2181		get_clause_prior(S,Head,Prior,M),
 2182		assertz(M:'$aleph_search'(clauseprior,Prior))
 2183	).
 2184reset_clause_prior(S,Head,M):-
 2185	copy_term(Head,Head1),
 2186	numbervars(Head1,0,_),
 2187	(M:'$aleph_local'(clauseprior,prior(Head1,Prior)) ->
 2188		true;
 2189		get_clause_prior(S,Head,Prior,M),
 2190		assertz(M:'$aleph_local'(clauseprior,prior(Head1,Prior)))
 2191	),
 2192	retractall(M:'$aleph_search'(clauseprior,_)),
 2193	assertz(M:'$aleph_search'(clauseprior,Prior)).
 2194
 2195get_clause_prior(S,Head,Total-[P-pos,N-neg],M):-
 2196	arg(5,S,Greedy),
 2197	arg(14,S,Depth),
 2198	arg(29,S,Time),
 2199	arg(34,S,Proof),
 2200	(Greedy = true ->
 2201		M:'$aleph_global'(atoms_left,atoms_left(pos,Pos));
 2202		M:'$aleph_global'(atoms,atoms(pos,Pos))
 2203	),
 2204	M:'$aleph_global'(atoms_left,atoms_left(neg,Neg)),
 2205	prove(Depth/Time/Proof,pos,(Head:-true),Pos,_,P,M),
 2206	prove(Depth/Time/Proof,neg,(Head:-true),Neg,_,N,M),
 2207	Total is P + N.
 2208
 2209get_user_refinement(auto,L,Clause,Template,0,M):-
 2210        auto_refine(L,Clause,Template,M).
 2211get_user_refinement(user,_,Clause,Template,0,M):-
 2212        M:refine(Clause,Template).
 2213
 2214match_bot(false,Clause,Clause,[],_M).
 2215match_bot(reduction,Clause,Clause1,Lits,M):-
 2216	match_lazy_bottom(Clause,Lits,M),
 2217	get_pclause(Lits,[],Clause1,_,_,_,M).
 2218match_bot(saturation,Clause,Clause1,Lits,M):-
 2219	once(get_aleph_clause(Clause,AlephClause)),
 2220	match_bot_lits(AlephClause,[],Lits,M),
 2221	get_pclause(Lits,[],Clause1,_,_,_,M).
 2222
 2223match_bot_lits((Lit,Lits),SoFar,[LitNum|LitNums],M):-
 2224	!,
 2225	match_bot_lit(Lit,LitNum,M),
 2226	\+(aleph_member(LitNum,SoFar)),
 2227	match_bot_lits(Lits,[LitNum|SoFar],LitNums,M).
 2228match_bot_lits(Lit,SoFar,[LitNum],M):-
 2229	match_bot_lit(Lit,LitNum,M),
 2230	\+(aleph_member(LitNum,SoFar)).
 2231
 2232match_bot_lit(Lit,LitNum,M):-
 2233	M:'$aleph_sat'(botsize,Last),
 2234	M:'$aleph_sat_litinfo'(LitNum,_,Lit,_,_,_),
 2235	LitNum >= 0,
 2236	LitNum =< Last.
 2237
 2238match_lazy_bottom(Clause,Lits,M):-
 2239	once(get_aleph_clause(Clause,AlephClause)),
 2240	copy_term(Clause,CClause),
 2241	split_clause(CClause,CHead,CBody),
 2242	example_saturated(CHead,M),
 2243	store(stage,M),
 2244	set(stage,saturation,M),
 2245	match_lazy_bottom1(CBody,M),
 2246	reinstate(stage,M),
 2247	match_bot_lits(AlephClause,[],Lits,M).
 2248
 2249match_lazy_bottom1(Body,M):-
 2250	M:Body,
 2251	match_body_modes(Body,M),
 2252	fail.
 2253match_lazy_bottom1(_,M):-
 2254	flatten_matched_atoms(body,M).
 2255
 2256match_body_modes((CLit,CLits),M):-
 2257        !,
 2258        match_mode(body,CLit,M),
 2259        match_body_modes(CLits,M).
 2260match_body_modes(CLit,M):-
 2261        match_mode(body,CLit,M).
 2262
 2263match_mode(_,true,_M):- !.
 2264match_mode(Loc,CLit,M):-
 2265	functor(CLit,Name,Arity),
 2266        functor(Mode,Name,Arity),
 2267	(Loc=head ->
 2268		M:'$aleph_global'(modeh,modeh(_,Mode));
 2269		M:'$aleph_global'(modeb,modeb(_,Mode))),
 2270        split_args(Mode,Mode,I,O,C,M),
 2271        (Loc = head ->
 2272		update_atoms(CLit,mode(Mode,O,I,C));
 2273		update_atoms(CLit,mode(Mode,I,O,C))),
 2274	fail.
 2275match_mode(_,_,_M).
 2276
 2277flatten_matched_atoms(Loc,M):-
 2278        setting(i,IVal,M),
 2279        (retract(M:'$aleph_sat'(botsize,BSize))-> true;  BSize = 0),
 2280        (retract(M:'$aleph_sat'(lastlit,Last))-> true ; Last = 0),
 2281        (Loc = head ->
 2282                flatten(0,IVal,BSize,BSize1);
 2283                flatten(0,IVal,Last,BSize1)),
 2284        asserta(M:'$aleph_sat'(botsize,BSize1)),
 2285	(Last < BSize1 -> 
 2286        	asserta(M:'$aleph_sat'(lastlit,BSize1));
 2287        	asserta(M:'$aleph_sat'(lastlit,Last))), !.
 2288flatten_matched_atoms(_,_M).
 2289
 2290% integrate head literal into lits database
 2291% used during lazy evaluation of bottom clause
 2292integrate_head_lit(HeadOVars,M):-
 2293        example_saturated(Example,M),
 2294	split_args(Example,_,_,Output,_,M),
 2295	integrate_args(unknown,Example,Output),
 2296        match_mode(head,Example,M),
 2297	flatten_matched_atoms(head,M),
 2298        get_ivars1(false,1,HeadOVars,M), !.
 2299integrate_head_lit([],_M).
 2300
 2301
 2302get_aleph_clause((Lit:-true),PLit):-
 2303	!,
 2304	get_aleph_lit(Lit,PLit).
 2305get_aleph_clause((Lit:-Lits),(PLit,PLits)):-
 2306	!,
 2307	get_aleph_lit(Lit,PLit),
 2308	get_aleph_lits(Lits,PLits).
 2309get_aleph_clause(Lit,PLit):-
 2310	get_aleph_lit(Lit,PLit).
 2311
 2312get_aleph_lits((Lit,Lits),(PLit,PLits)):-
 2313	!,
 2314	get_aleph_lit(Lit,PLit),
 2315	get_aleph_lits(Lits,PLits).
 2316get_aleph_lits(Lit,PLit):-
 2317	get_aleph_lit(Lit,PLit).
 2318
 2319get_aleph_lit(Lit,PLit):-
 2320	functor(Lit,Name,Arity),
 2321	functor(PLit,Name,Arity),
 2322	get_aleph_lit(Lit,PLit,Arity).
 2323
 2324get_aleph_lit(_,_,0):- !.
 2325get_aleph_lit(Lit,PLit,Arg):-
 2326	arg(Arg,Lit,Term),
 2327	(var(Term) -> arg(Arg,PLit,Term);arg(Arg,PLit,aleph_const(Term))),
 2328	NextArg is Arg - 1,
 2329	get_aleph_lit(Lit,PLit,NextArg), !.
 2330	
 2331% Claudien-style consistency checking as described by De Raedt and Dehaspe, 1996
 2332% currently does not retain actual substitutions that result in inconsistencies
 2333% also, only checks for constraints of the form false:- ...
 2334% this simplifies the check of Body,not(Head) to just Body
 2335ccheck(S,(aleph_false:-Body),[],[0,N|_],M):-
 2336	(Body = true ->
 2337		N is inf;
 2338		arg(11,S,LContra),
 2339		(LContra = false -> 
 2340        		arg(14,S,Depth),
 2341        		arg(29,S,Time),
 2342			findall(X,(resource_bound_call(Time,Depth,Body,M),X=1),XL),
 2343			length(XL,N);
 2344			lazy_ccheck(S,Body,N,M)
 2345		)
 2346	).
 2347
 2348lazy_ccheck(S,Body,N,M):-
 2349        arg(14,S,Depth),
 2350        arg(17,S,Noise),
 2351        arg(29,S,Time),
 2352	retractall(M:'$aleph_local'(subst_count,_)),
 2353	asserta(M:'$aleph_local'(subst_count,0)),
 2354	resource_bound_call(Time,Depth,Body,M),
 2355	retract(M:'$aleph_local'(subst_count,N0)),
 2356	N is N0 + 1,
 2357	N > Noise, !.
 2358lazy_ccheck(_,_,N,M):-
 2359	retract(M:'$aleph_local'(subst_count,N)).
 2360
 2361% posonly formula as described by Muggleton, ILP-96
 2362prove_examples(S,Flag,Contradiction,Entry,Best,CL,L2,Clause,Pos,Rand,PCover,RCover,[P,B,CL,I,G],M):-
 2363	
 2364	arg(4,S,_/Evalfn),
 2365	Evalfn = posonly, !,
 2366        arg(11,S,LazyOnContra),
 2367        ((LazyOnContra = true, Contradiction = true) ->
 2368                prove_lazy_cached(S,Entry,Pos,Rand,PCover,RCover,M),
 2369                interval_count(PCover,_PC),
 2370                interval_count(RCover,RC);
 2371                prove_pos(S,Flag,Entry,Best,[PC,L2],Clause,Pos,PCover,PC,M),
 2372                prove_rand(S,Flag,Entry,Clause,Rand,RCover,RC,M)),
 2373        find_posgain(PCover,P,M),
 2374        arg(16,S,MM), arg(20,S,N),
 2375        GC is (RC+1.0)/(N+2.0), % Laplace correction for small numbers
 2376        A is log(P),
 2377        B is log(GC),
 2378        G is GC*MM/P,
 2379        C is CL/P,
 2380        % Sz is CL*M/P,
 2381        % D is M*G,
 2382        %  I is M - D - Sz,
 2383        I is A - B - C.
 2384prove_examples(S,_,_,Entry,_,CL,_,_,Pos,Neg,Pos,Neg,[PC,NC,CL],M):-
 2385		
 2386        arg(10,S,LazyOnCost),
 2387        LazyOnCost = true, !,
 2388        prove_lazy_cached(S,Entry,Pos,Neg,Pos1,Neg1,M),
 2389        interval_count(Pos1,PC),
 2390        interval_count(Neg1,NC).
 2391prove_examples(S,_,true,Entry,_,CL,_,_,Pos,Neg,Pos,Neg,[PC,NC,CL],M):-
 2392		
 2393        arg(11,S,LazyOnContra),
 2394        LazyOnContra = true, !,
 2395        prove_lazy_cached(S,Entry,Pos,Neg,Pos1,Neg1,M),
 2396        interval_count(Pos1,PC),
 2397        interval_count(Neg1,NC).
 2398prove_examples(S,Flag,_,Ent,Best,CL,L2,Clause,Pos,Neg,PCover,NCover,[PC,NC,CL],M):-
 2399	
 2400	arg(3,S,RefineOp),
 2401	(RefineOp = false; RefineOp = auto),
 2402        arg(7,S,ClauseLength),
 2403        ClauseLength = CL, !,
 2404	interval_count(Pos,MaxPCount),
 2405        prove_neg(S,Flag,Ent,Best,[MaxPCount,CL],Clause,Neg,NCover,NC,M),
 2406        arg(17,S,Noise), arg(18,S,MinAcc),
 2407        maxlength_neg_ok(Noise/MinAcc,Ent,MaxPCount,NC,M),
 2408        prove_pos(S,Flag,Ent,Best,[PC,L2],Clause,Pos,PCover,PC,M),
 2409        maxlength_neg_ok(Noise/MinAcc,Ent,PC,NC,M),
 2410	!.
 2411prove_examples(S,Flag,_,Ent,Best,CL,L2,Clause,Pos,Neg,PCover,NCover,[PC,NC,CL],M):-
 2412        prove_pos(S,Flag,Ent,Best,[PC,L2],Clause,Pos,PCover,PC,M),
 2413        prove_neg(S,Flag,Ent,Best,[PC,CL],Clause,Neg,NCover,NC,M),
 2414	!.
 2415
 2416prove_lazy_cached(S,Entry,Pos,Neg,Pos1,Neg1,M):-
 2417        arg(8,S,Caching),
 2418	Caching = true, !,
 2419	(check_cache(Entry,pos,Pos1,M)->
 2420		true;
 2421		add_cache(Entry,pos,Pos,M),
 2422		Pos1 = Pos),
 2423	(check_cache(Entry,neg,Neg1,M)->
 2424		true;
 2425		add_cache(Entry,neg,Neg,M),
 2426		Neg1 = Neg).
 2427prove_lazy_cached(_,_,Pos,Neg,Pos,Neg,_M).
 2428
 2429complete_label(posonly,_,L,L,_M):- !.
 2430complete_label(user,Clause,[P,N,L],[P,N,L,Val],M):-
 2431        M:cost(Clause,[P,N,L],Cost), !,
 2432	Val is -Cost.
 2433complete_label(entropy,_,[P,N,L],[P,N,L,Val],M):-
 2434	evalfn(entropy,[P,N,L],Entropy,M),
 2435	Val is -Entropy, !.
 2436complete_label(gini,_,[P,N,L],[P,N,L,Val],M):-
 2437	evalfn(gini,[P,N,L],Gini,M),
 2438	Val is -Gini, !.
 2439complete_label(EvalFn,_,[P,N,L],[P,N,L,Val],M):-
 2440	evalfn(EvalFn,[P,N,L],Val,M), !.
 2441complete_label(_,_,_,_,_M):-
 2442	p_message1('error'), p_message('incorrect evaluation/cost function'),
 2443	fail.
 2444
 2445% estimate label based on subsampling
 2446estimate_label(Sample,[P,N|Rest],[P1,N1|Rest],M):-
 2447	M:'$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 2448	M:'$aleph_global'(atoms_left,atoms_left(neg,Neg)),
 2449	interval_count(Pos,PC), interval_count(Neg,NC),
 2450	PFrac is P/Sample,
 2451	NFrac is N/Sample,
 2452	P1 is integer(PFrac*PC),
 2453	N1 is integer(NFrac*NC).
 2454
 2455% get primary and secondary search keys for search
 2456% use [Primary|Secondary] notation as it is the most compact
 2457get_search_keys(bf,[_,_,L,F|_],[L1|F]):-
 2458	!,
 2459	L1 is -1*L.
 2460get_search_keys(df,[_,_,L,F|_],[L|F]):- !.
 2461get_search_keys(_,[_,_,L,F|_],[F|L1]):-
 2462	L1 is -1*L.
 2463
 2464prove_pos(_,_,_,_,_,_,[],[],0,_M):- !.
 2465prove_pos(S,_,Entry,BestSoFar,PosSoFar,Clause,_,PCover,PCount,M):-
 2466        M:'$aleph_search'(covers,covers(PCover,PCount)), !,
 2467        pos_ok(S,Entry,BestSoFar,PosSoFar,Clause,PCover,M).
 2468prove_pos(S,Flag,Entry,BestSoFar,PosSoFar,Clause,Pos,PCover,PCount,M):-
 2469        prove_cache(Flag,S,pos,Entry,Clause,Pos,PCover,PCount,M),
 2470        pos_ok(S,Entry,BestSoFar,PosSoFar,Clause,PCover,M), !.
 2471
 2472prove_neg(S,_,Entry,_,_,_,[],[],0,M):-
 2473	arg(8,S,Caching),
 2474	(Caching = true -> add_cache(Entry,neg,[],M); true), !.
 2475prove_neg(S,Flag,Entry,_,_,Clause,Neg,NCover,NCount,M):-
 2476	arg(3,S,RefineOp),
 2477	RefineOp = rls,  !,
 2478        prove_cache(Flag,S,neg,Entry,Clause,Neg,NCover,NCount,M).
 2479prove_neg(_,_,_,_,_,_,_,NCover,NCount,M):-
 2480        M:'$aleph_search'(coversn,coversn(NCover,NCount)), !.
 2481prove_neg(S,Flag,Entry,BestSoFar,PosSoFar,Clause,Neg,NCover,NCount,M):-
 2482        arg(12,S,LazyNegs),
 2483        LazyNegs = true, !,
 2484        lazy_prove_neg(S,Flag,Entry,BestSoFar,PosSoFar,Clause,Neg,NCover,NCount,M).
 2485prove_neg(S,Flag,Entry,[P,0,L1|_],[P,L2],Clause,Neg,[],0,M):-
 2486	arg(4,S,bf/coverage),
 2487        L2 is L1 - 1,
 2488	!,
 2489        prove_cache(Flag,S,neg,Entry,Clause,Neg,0,[],0,M), !.
 2490prove_neg(S,Flag,Entry,[P,N|_],[P,L1],Clause,Neg,NCover,NCount,M):-
 2491	arg(4,S,bf/coverage),
 2492        !,
 2493        arg(7,S,ClauseLength),
 2494        (ClauseLength = L1 ->
 2495		arg(2,S,Explore),
 2496		(Explore = true -> MaxNegs is N; MaxNegs is N - 1),
 2497                MaxNegs >= 0,
 2498                prove_cache(Flag,S,neg,Entry,Clause,Neg,MaxNegs,NCover,NCount,M),
 2499		NCount =< MaxNegs;
 2500                prove_cache(Flag,S,neg,Entry,Clause,Neg,NCover,NCount,M)),
 2501        !.
 2502prove_neg(S,Flag,Entry,_,[P1,L1],Clause,Neg,NCover,NCount,M):-
 2503        arg(7,S,ClauseLength),
 2504        ClauseLength = L1,  !,
 2505        arg(17,S,Noise), arg(18,S,MinAcc),
 2506        get_max_negs(Noise/MinAcc,P1,N1),
 2507        prove_cache(Flag,S,neg,Entry,Clause,Neg,N1,NCover,NCount,M),
 2508	NCount =< N1,
 2509        !.
 2510prove_neg(S,Flag,Entry,_,_,Clause,Neg,NCover,NCount,M):-
 2511        prove_cache(Flag,S,neg,Entry,Clause,Neg,NCover,NCount,M),
 2512        !.
 2513
 2514prove_rand(S,Flag,Entry,Clause,Rand,RCover,RCount,M):-
 2515        prove_cache(Flag,S,rand,Entry,Clause,Rand,RCover,RCount,M),
 2516        !.
 2517
 2518lazy_prove_neg(S,Flag,Entry,[P,N|_],[P,_],Clause,Neg,NCover,NCount,M):-
 2519	arg(4,S,bf/coverage),
 2520        !,
 2521        MaxNegs is N + 1,
 2522        prove_cache(Flag,S,neg,Entry,Clause,Neg,MaxNegs,NCover,NCount,M),
 2523        !.
 2524lazy_prove_neg(S,Flag,Entry,_,[P1,_],Clause,Neg,NCover,NCount,M):-
 2525        arg(17,S,Noise), arg(18,S,MinAcc),
 2526        get_max_negs(Noise/MinAcc,P1,N1),
 2527        MaxNegs is N1 + 1,
 2528        prove_cache(Flag,S,neg,Entry,Clause,Neg,MaxNegs,NCover,NCount,M),
 2529        !.
 2530
 2531% Bug reported by Daniel Fredouille
 2532% For MiAcc =:= 0, Negs was being set to P1 + 1. Unclear why.
 2533% This definition is as it was up to Aleph 2.
 2534get_max_negs(Noise/MinAcc,P1,N):-
 2535        number(P1), 
 2536	(MinAcc =:= 0.0 -> N is Noise;
 2537        	(N1 is integer((1-MinAcc)*P1/MinAcc),
 2538		(Noise < N1 -> N is Noise; N is N1))
 2539	), !.
 2540get_max_negs(Noise/_,_,Noise).
 2541
 2542
 2543% update_open_list(+SearchKeys,+NodeRef,+Label)
 2544% insert SearchKeys into openlist
 2545update_open_list([K1|K2],NodeRef,Label,M):-
 2546	assertz(M:'$aleph_search_gain'(K1,K2,NodeRef,Label)),
 2547	retract(M:'$aleph_search'(openlist,OpenList)),
 2548	uniq_insert(descending,[K1|K2],OpenList,List1),
 2549	asserta(M:'$aleph_search'(openlist,List1)).
 2550
 2551pos_ok(S,_,_,_,_,_,_M):-
 2552	arg(3,S,RefineOp),
 2553	(RefineOp = rls; RefineOp = user),  !.
 2554pos_ok(S,Entry,_,[P,_],_,_,M):-
 2555        arg(13,S,MinPos),
 2556        P < MinPos, !,
 2557        arg(8,S,Caching),
 2558        (Caching = true ->
 2559                add_prune_cache(Entry,M);
 2560                true),
 2561        fail.
 2562pos_ok(S,Entry,_,[P,_],_,_,M):-
 2563	arg(40,S,MinPosFrac),
 2564	MinPosFrac > 0.0,
 2565	M:'$aleph_search'(clauseprior,_-[P1-pos,_]),
 2566	P/P1 < MinPosFrac, !,
 2567        arg(8,S,Caching),
 2568        (Caching = true ->
 2569                add_prune_cache(Entry,M);
 2570                true),
 2571	fail.
 2572pos_ok(S,_,[_,_,_,C1|_],[P,L],_,_,M):-
 2573        arg(4,S,_/Evalfn),
 2574	arg(2,S,Explore),
 2575	((Evalfn = user; Explore = true) -> true;
 2576        	evalfn(Evalfn,[P,0,L],C2,M),
 2577		best_value(Evalfn,S,[P,0,L,C2],Max,M),
 2578        	Max > C1), !.
 2579
 2580
 2581maxlength_neg_ok(Noise/MinAcc,Entry,P,N,M):-
 2582	((N > Noise); (P/(P+N) < MinAcc)), !,
 2583        add_prune_cache(Entry,M),
 2584	fail.
 2585maxlength_neg_ok(_,_,_,_,_M).
 2586
 2587compression_ok(compression,[P,_,L|_]):-
 2588	!,
 2589	P - L + 1 > 0.
 2590compression_ok(_,_).
 2591
 2592length_ok(S,MinLen,ClauseLen,LastD,ExpectedMin,ExpectedCLen):-
 2593        arg(3,S,RefineOp),
 2594        (RefineOp = false  -> L1 = LastD; L1 = 0),
 2595        (L1 < MinLen->ExpectedMin = L1;ExpectedMin = MinLen),
 2596        ExpectedCLen is ClauseLen + ExpectedMin,
 2597        arg(7,S,CLength),
 2598        ExpectedCLen =< CLength, !.
 2599
 2600update_best(S,_,_,_,Best,[P,_,_,F|_]/_,Best,_M):-
 2601        arg(13,S,MinPos),
 2602        arg(19,S,MinScore),
 2603	(P < MinPos;  F is -inf; F < MinScore), !.
 2604update_best(S,_,_,_,Best,[P|_]/_,Best,M):-
 2605	arg(40,S,MinPosFrac),
 2606	MinPosFrac > 0.0,
 2607	M:'$aleph_search'(clauseprior,_-[P1-pos,_]),
 2608	P/P1 < MinPosFrac, !.
 2609update_best(S,_,_,_,Best,[P,N,_,_|_]/_,Best,_M):-
 2610        arg(4,S,_/Evalfn),
 2611	Evalfn \= posonly,
 2612	% Evalfn \= user,
 2613        arg(17,S,Noise),
 2614        arg(18,S,MinAcc),
 2615	arg(22,S,Search),
 2616	Total is P + N,
 2617	((N > Noise);(Search \= ic, Total > 0, P/Total < MinAcc)),   !.
 2618update_best(S,Clause,PCover,NCover,Label/_,Label1/Node1,Label1/Node1,M):-
 2619        Label = [_,_,_,GainE|_],
 2620        Label1 = [_,_,_,Gain1E|_],
 2621	arithmetic_expression_value(GainE,Gain),
 2622	arithmetic_expression_value(Gain1E,Gain1),
 2623        % (Gain1 = inf; Gain = -inf; Gain1 > Gain), !,
 2624	Gain1 > Gain, !,
 2625	retractall(M:'$aleph_search'(selected,_)),
 2626        asserta(M:'$aleph_search'(selected,selected(Label1,Clause,PCover,NCover))),
 2627        arg(35,S,VSearch),
 2628        (VSearch = true ->
 2629		retractall(M:'$aleph_search'(best,_)),
 2630                asserta(M:'$aleph_search'(best,Node1)),
 2631                asserta(M:'$aleph_search'(good,Node1));
 2632                true),
 2633	update_good(Label1,Clause,M),
 2634        show_clause(newbest,Label1,Clause,Node1,M),
 2635        record_clause(newbest,Label1,Clause,Node1,M),
 2636        record_clause(good,Label1,Clause,Node1,M).
 2637update_best(S,Clause,_,_,Label/Node,Label1/Node1,Label/Node,M):-
 2638        arg(35,S,VSearch),
 2639        (VSearch = true ->
 2640                asserta(M:'$aleph_search'(good,Node1));
 2641                true),
 2642	update_good(Label1,Clause,M),
 2643        show_clause(good,Label1,Clause,Node1,M),
 2644        record_clause(good,Label1,Clause,Node1,M).
 2645
 2646update_good(Label,Clause,M):- 
 2647	setting(good,true,M), !,
 2648	Label = [_,_,L|_],
 2649	setting(check_good,Flag,M),
 2650	update_good(Flag,L,Label,Clause,M).
 2651update_good(_,_,_M).
 2652
 2653update_good(_,_,_,_,M):-
 2654	setting(goodfile,_,M), !.
 2655update_good(true,L,Label,Clause,M):-
 2656	M:'$aleph_good'(L,Label,Clause), !.
 2657update_good(_,L,Label,Clause,M):-
 2658	assertz(M:'$aleph_good'(L,Label,Clause)),
 2659	(retract(M:'$aleph_search'(last_good,Good)) ->
 2660		Good1 is Good + 1;
 2661		Good1 is 1),
 2662	assertz(M:'$aleph_search'(last_good,Good1)).
 2663
 2664update_best_theory(S,_,_,_,Best,[P,N,_,F|_]/_,Best,_M):-
 2665	arg(17,S,Noise),
 2666	arg(18,S,MinAcc),
 2667	arg(19,S,MinScore),
 2668	(N > Noise; P/(P+N) < MinAcc; F < MinScore),  !.
 2669update_best_theory(_,Theory,PCover,NCover,Label/_,Label1/Node1,Label1/Node1,M):-
 2670	Label = [_,_,_,GainE|_],
 2671	Label1 = [_,_,_,Gain1E|_],
 2672	arithmetic_expression_value(GainE,Gain),
 2673	arithmetic_expression_value(Gain1E,Gain1),
 2674	Gain1 > Gain, !, 
 2675	retractall(M:'$aleph_search'(selected,_)),
 2676        asserta(M:'$aleph_search'(selected,selected(Label1,Theory,PCover,NCover))),
 2677	show_theory(newbest,Label1,Theory,Node1,M),
 2678	record_theory(newbest,Label1,Theory,Node1,M),
 2679	record_theory(good,Label1,Theory,Node1,M).
 2680update_best_theory(_,Theory,_,_,Best,Label1/_,Best,M):-
 2681	show_theory(good,Label1,Theory,Node1,M),
 2682	record_theory(good,Label1,Theory,Node1,M).
 2683
 2684%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 2685% P R U N I N G   C L A U S E S
 2686
 2687get_node([[K1|K2]|_],[K1|K2],Node,M):-
 2688        M:'$aleph_search_gain'(K1,K2,Node,_).
 2689get_node([_|Gains],Gain,Node,M):-
 2690	get_node(Gains,Gain,Node,M).
 2691
 2692prune_open(S,_,_,M):-
 2693	arg(25,S,OSize),
 2694	Inf is inf,
 2695	OSize =\= Inf,
 2696        retractall(M:'$aleph_local'(in_beam,_)),
 2697        asserta(M:'$aleph_local'(in_beam,0)),
 2698        M:'$aleph_search'(openlist,Gains),
 2699        get_node(Gains,[K1|K2],NodeNum,M),
 2700        M:'$aleph_local'(in_beam,N),
 2701        (N < OSize->
 2702        	retract(M:'$aleph_local'(in_beam,N)),
 2703                N1 is N + 1,
 2704                asserta(M:'$aleph_local'(in_beam,N1));
 2705		retract(M:'$aleph_search_gain'(K1,K2,NodeNum,_)),
 2706		arg(6,S,Verbose),
 2707                (Verbose < 1 ->
 2708			true;
 2709			p1_message('non-admissible removal'),
 2710			p_message(NodeNum))),
 2711        fail.
 2712prune_open(S,_,_,_M):-
 2713        arg(2,S,Explore),
 2714        arg(3,S,RefineOp),
 2715	(Explore = true; RefineOp = rls; RefineOp = user), !.
 2716prune_open(_,_/N,_/N,_M):- !.
 2717prune_open(S,_,[_,_,_,Best|_]/_,M):-
 2718        arg(4,S,_/Evalfn),
 2719	built_in_prune(Evalfn),
 2720        M:'$aleph_search_gain'(_,_,_,Label),
 2721	best_value(Evalfn,S,Label,Best1,M),
 2722	Best1 =< Best, 
 2723        retract(M:'$aleph_search_gain'(_,_,_,Label)),
 2724	fail.
 2725prune_open(_,_,_,_M).
 2726
 2727built_in_prune(coverage).
 2728built_in_prune(compression).
 2729built_in_prune(posonly).
 2730built_in_prune(laplace).
 2731built_in_prune(wracc).
 2732built_in_prune(mestimate).
 2733built_in_prune(auto_m).
 2734
 2735% pruning for posonly, laplace and m-estimates devised in
 2736%	discussion with James Cussens
 2737% pruning for weighted relative accuracy devised in
 2738%	discussion with Steve Moyle
 2739% corrections to best_value/4 after discussion with
 2740% Mark Reid and James Cussens
 2741best_value(gini,_,_,0.0,_M):- !.
 2742best_value(entropy,_,_,0.0,_M):- !.
 2743best_value(posonly,S,[P,_,L|_],Best,_M):-
 2744	arg(20,S,RSize),
 2745	Best is log(P) + log(RSize+2.0) - (L+1)/P, !.
 2746best_value(wracc,_,[P|_],Best,M):-
 2747	(M:'$aleph_search'(clauseprior,Total-[P1-pos,_]) ->
 2748		Best is P*(Total - P1)/(Total^2);
 2749		Best is 0.25), !.
 2750best_value(Evalfn,_,[P,_,L|Rest],Best,M):-
 2751	L1 is L + 1,	% need at least 1 extra literal to achieve best value
 2752	evalfn(Evalfn,[P,0,L1|Rest],Best,M).
 2753
 2754
 2755get_nextbest(S,NodeRef,M):-
 2756        arg(22,S,Search),
 2757	select_nextbest(Search,NodeRef,M).
 2758
 2759% Select the next best node
 2760% Incorporates the changes made by Filip Zelezny to
 2761% achieve the `randomised rapid restart' (or rrr) technique
 2762% within randomised local search
 2763select_nextbest(rls,NodeRef,M):-
 2764	retractall(M:'$aleph_search'(nextnode,_)),
 2765        setting(rls_type,Type,M),
 2766        (retract(M:'$aleph_search'(rls_parentstats,stats(PStats,_,_))) -> true; true),
 2767        (rls_nextbest(Type,PStats,NodeRef,Label,M) ->
 2768                asserta(M:'$aleph_search'(rls_parentstats,stats(Label,[],[]))),
 2769                setting(rls_type,RlsType,M),
 2770                (RlsType = rrr ->
 2771                      true;
 2772                      assertz(M:'$aleph_search'(nextnode,NodeRef)));
 2773                NodeRef = none), !.
 2774select_nextbest(_,NodeRef,M):-
 2775	retractall(M:'$aleph_search'(nextnode,_)),
 2776	get_nextbest(NodeRef,M), !.
 2777select_nextbest(_,none,_M).
 2778
 2779get_nextbest(NodeRef,M):-
 2780        M:'$aleph_search'(openlist,[H|_]),
 2781	H = [K1|K2],
 2782        retract(M:'$aleph_search_gain'(K1,K2,NodeRef,_)),
 2783        assertz(M:'$aleph_search'(nextnode,NodeRef)).
 2784get_nextbest(NodeRef,M):-
 2785        retract(M:'$aleph_search'(openlist,[_|T])),
 2786        asserta(M:'$aleph_search'(openlist,T)),
 2787        get_nextbest(NodeRef,M), !.
 2788get_nextbest(none,_M).
 2789
 2790rls_nextbest(rrr,_,NodeRef,_,M):-
 2791        get_nextbest(NodeRef,M).
 2792rls_nextbest(gsat,_,NodeRef,Label,M):-
 2793        retract(M:'$aleph_search'(openlist,[H|_])),
 2794	H = [K1|K2],
 2795	asserta(M:'$aleph_search'(openlist,[])),
 2796	findall(N-L,M:'$aleph_search_gain'(K1,K2,N,L),Choices),
 2797	length(Choices,Last),
 2798	get_random(Last,N),
 2799	aleph_remove_nth(N,Choices,NodeRef-Label,_),
 2800	retractall(M:'$aleph_search_gain'(_,_,_,_)).
 2801rls_nextbest(wsat,PStats,NodeRef,Label,M):-
 2802	setting(walk,WProb,M),
 2803	aleph_random(P),
 2804	P >= WProb, !,
 2805	rls_nextbest(gsat,PStats,NodeRef,Label,M).
 2806rls_nextbest(wsat,PStats,NodeRef,Label,M):-
 2807	p_message('random walk'),
 2808        retract(M:'$aleph_search'(openlist,_)),
 2809	asserta(M:'$aleph_search'(openlist,[])),
 2810	findall(N-L,M:'$aleph_search_gain'(_,_,N,L),AllNodes),
 2811	potentially_good(AllNodes,PStats,Choices),
 2812        length(Choices,Last),
 2813        get_random(Last,N),
 2814        aleph_remove_nth(N,Choices,NodeRef-Label,_),
 2815	retractall(M:'$aleph_search_gain'(_,_,_,_)).
 2816rls_nextbest(anneal,[P,N|_],NodeRef,Label,M):-
 2817	setting(temperature,Temp,M),
 2818        retract(M:'$aleph_search'(openlist,_)),
 2819	asserta(M:'$aleph_search'(openlist,[])),
 2820	findall(N-L,M:'$aleph_search_gain'(_,_,N,L),AllNodes),
 2821	length(AllNodes,Last),
 2822	get_random(Last,S),
 2823	aleph_remove_nth(S,AllNodes,NodeRef-Label,_),
 2824	Label = [P1,N1|_],
 2825	Gain is (P1 - N1) - (P - N),
 2826	((P = 1); (Gain >= 0);(aleph_random(R), R < exp(Gain/Temp))).
 2827
 2828potentially_good([],_,[]).
 2829potentially_good([H|T],Label,[H|T1]):-
 2830        H = _-Label1,
 2831        potentially_good(Label,Label1), !,
 2832        potentially_good(T,Label,T1).
 2833potentially_good([_|T],Label,T1):-
 2834        potentially_good(T,Label,T1).
 2835
 2836potentially_good([1|_],[P1|_]):-
 2837        !,
 2838        P1 > 1.
 2839potentially_good([P,_,L|_],[P1,_,L1|_]):-
 2840        L1 =< L, !,
 2841        P1 > P.
 2842potentially_good([_,N|_],[_,N1|_]):-
 2843        N1 < N.
 2844
 2845
 2846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 2847% P R O V E
 2848
 2849% prove with caching
 2850% if entry exists in cache, then return it
 2851% otherwise find and cache cover 
 2852% if ``exact'' flag is set then only check proof for examples
 2853% in the part left over due to lazy theorem-proving
 2854% ideas in caching developed in discussions with James Cussens
 2855
 2856prove_cache(exact,S,Type,Entry,Clause,Intervals,IList,Count,M):-
 2857	!,
 2858	(Intervals = Exact/Left ->
 2859        	arg(14,S,Depth),
 2860        	arg(29,S,Time),
 2861        	arg(34,S,Proof),
 2862        	prove(Depth/Time/Proof,Type,Clause,Left,IList1,Count1,M),
 2863		aleph_append(IList1,Exact,IList),
 2864		interval_count(Exact,Count0),
 2865		Count is Count0 + Count1;
 2866		IList = Intervals,
 2867		interval_count(IList,Count)),
 2868        arg(8,S,Caching),
 2869        (Caching = true -> add_cache(Entry,Type,IList); true).
 2870prove_cache(upper,S,Type,Entry,Clause,Intervals,IList,Count,M):-
 2871        arg(8,S,Caching),
 2872        Caching = true, !,
 2873        arg(14,S,Depth),
 2874        arg(29,S,Time),
 2875        arg(34,S,Proof),
 2876        (check_cache(Entry,Type,Cached,M)->
 2877                prove_cached(S,Type,Entry,Cached,Clause,Intervals,IList,Count,M);
 2878                prove_intervals(Depth/Time/Proof,Type,Clause,Intervals,IList,Count,M),
 2879                add_cache(Entry,Type,IList,M)).
 2880prove_cache(upper,S,Type,_,Clause,Intervals,IList,Count,M):-
 2881        arg(14,S,Depth),
 2882        arg(29,S,Time),
 2883        arg(34,S,Proof),
 2884	(Intervals = Exact/Left ->
 2885		aleph_append(Left,Exact,IList1),
 2886        	prove(Depth/Time/Proof,Type,Clause,IList1,IList,Count,M);
 2887        	prove(Depth/Time/Proof,Type,Clause,Intervals,IList,Count,M)).
 2888
 2889prove_intervals(DepthTime,Type,Clause,I1/Left,IList,Count,M):- 
 2890	!,
 2891	aleph_append(Left,I1,Intervals),
 2892	prove(DepthTime,Type,Clause,Intervals,IList,Count,M).
 2893prove_intervals(DepthTime,Type,Clause,Intervals,IList,Count,M):- 
 2894	prove(DepthTime,Type,Clause,Intervals,IList,Count,M).
 2895
 2896prove_cached(S,Type,Entry,I1/Left,Clause,Intervals,IList,Count,M):-
 2897        !,
 2898        arg(14,S,Depth),
 2899        arg(29,S,Time),
 2900        arg(34,S,Proof),
 2901        prove(Depth/Time/Proof,Type,Clause,Left,I2,_,M),
 2902        aleph_append(I2,I1,I),
 2903        (Type = pos ->
 2904                arg(5,S,Greedy),
 2905                (Greedy = true ->
 2906                        intervals_intersection(I,Intervals,IList);
 2907                        IList = I);
 2908                IList = I),
 2909        interval_count(IList,Count),
 2910        update_cache(Entry,Type,IList,M).
 2911prove_cached(S,Type,Entry,I1,_,Intervals,IList,Count,M):-
 2912	(Type = pos -> arg(5,S,Greedy),
 2913		(Greedy = true ->
 2914			intervals_intersection(I1,Intervals,IList);
 2915			IList = I1);
 2916		IList = I1),
 2917	interval_count(IList,Count),
 2918	update_cache(Entry,Type,IList,M).
 2919
 2920% prove at most Max atoms
 2921prove_cache(exact,S,Type,Entry,Clause,Intervals,Max,IList,Count,M):-
 2922	!,
 2923	(Intervals = Exact/Left ->
 2924		interval_count(Exact,Count0),
 2925		Max1 is Max - Count0,
 2926        	arg(12,S,LNegs),
 2927        	arg(14,S,Depth),
 2928        	arg(29,S,Time),
 2929        	arg(34,S,Proof),
 2930        	prove(LNegs/false,Depth/Time/Proof,Type,Clause,Left,Max1,IList1,Count1,M),
 2931		aleph_append(IList1,Exact,Exact1),
 2932		find_lazy_left(S,Type,Exact1,Left1),
 2933		IList = Exact1/Left1,
 2934		Count is Count0 + Count1;
 2935		IList = Intervals,
 2936		interval_count(Intervals,Count)),
 2937        arg(8,S,Caching),
 2938        (Caching = true -> add_cache(Entry,Type,IList); true).
 2939prove_cache(upper,S,Type,Entry,Clause,Intervals,Max,IList,Count,M):-
 2940        arg(8,S,Caching),
 2941        Caching = true, !,
 2942        (check_cache(Entry,Type,Cached,M)->
 2943                prove_cached(S,Type,Entry,Cached,Clause,Intervals,Max,IList,Count,M);
 2944                (prove_intervals(S,Type,Clause,Intervals,Max,IList1,Count,M)->
 2945                        find_lazy_left(S,Type,IList1,Left1),
 2946                        add_cache(Entry,Type,IList1/Left1,M),
 2947			IList = IList1/Left1,
 2948                        retractall(M:'$aleph_local'(example_cache,_));
 2949                        collect_example_cache(IList,M),
 2950                        add_cache(Entry,Type,IList,M),
 2951                        fail)).
 2952prove_cache(upper,S,Type,_,Clause,Intervals,Max,IList/Left1,Count,M):-
 2953        arg(8,S,Caching),
 2954        arg(12,S,LNegs),
 2955        arg(14,S,Depth),
 2956        arg(29,S,Time),
 2957        arg(34,S,Proof),
 2958	(Intervals = Exact/Left ->
 2959		aleph_append(Left,Exact,IList1),
 2960        	prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,IList1,Max,IList,Count,M);
 2961        	prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,Intervals,Max,IList,Count,M)),
 2962	find_lazy_left(S,Type,IList,Left1).
 2963
 2964prove_intervals(S,Type,Clause,I1/Left,Max,IList,Count,M):-
 2965        !,
 2966        arg(8,S,Caching),
 2967        arg(12,S,LNegs),
 2968        arg(14,S,Depth),
 2969        arg(29,S,Time),
 2970        arg(34,S,Proof),
 2971        aleph_append(Left,I1,Intervals),
 2972        prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,Intervals,Max,IList,Count,M).
 2973prove_intervals(S,Type,Clause,Intervals,Max,IList,Count,M):-
 2974        arg(8,S,Caching),
 2975        arg(12,S,LNegs),
 2976        arg(14,S,Depth),
 2977        arg(29,S,Time),
 2978        arg(34,S,Proof),
 2979        prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,Intervals,Max,IList,Count,M).
 2980
 2981
 2982prove_cached(S,Type,Entry, I1/Left,Clause,_,Max,IList/Left1,Count,M):-
 2983        !,
 2984        arg(8,S,Caching),
 2985        arg(12,S,LNegs),
 2986        arg(14,S,Depth),
 2987        arg(29,S,Time),
 2988        arg(34,S,Proof),
 2989        interval_count(I1,C1),
 2990        Max1 is Max - C1,
 2991        Max1 >= 0,
 2992        (prove(LNegs/Caching,Depth/Time/Proof,Type,Clause,Left,Max1,I2,C2,M)->
 2993                aleph_append(I2,I1,IList),
 2994                Count is C2 + C1,
 2995                find_lazy_left(S,Type,IList,Left1),
 2996                update_cache(Entry,Type,IList/Left1,M),
 2997                retractall(M:'$aleph_local'(example_cache,_));
 2998                collect_example_cache(I2/Left1,M),
 2999                aleph_append(I2,I1,IList),
 3000                update_cache(Entry,Type,IList/Left1,M),
 3001                fail).
 3002prove_cached(_,neg,_, I1/L1,_,_,_,I1/L1,C1,_M):-
 3003	!,
 3004	interval_count(I1,C1).
 3005prove_cached(S,_,_,I1,_,_,Max,I1,C1,_M):-
 3006	interval_count(I1,C1),
 3007	arg(12,S,LNegs),
 3008	(LNegs = true ->true; C1 =< Max).
 3009
 3010collect_example_cache(Intervals/Left,M):-
 3011	retract(M:'$aleph_local'(example_cache,[Last|Rest])),
 3012	aleph_reverse([Last|Rest],IList),
 3013	list_to_intervals1(IList,Intervals),
 3014	Next is Last + 1,
 3015	M:'$aleph_global'(size,size(neg,LastN)),
 3016	(Next > LastN -> Left = []; Left = [Next-LastN]).
 3017
 3018find_lazy_left(S,_,_,[]):-
 3019        arg(12,S,LazyNegs),
 3020        LazyNegs = false, !.
 3021find_lazy_left(_,_,[],[]).
 3022find_lazy_left(S,Type,[_-F],Left):-
 3023        !,
 3024        F1 is F + 1,
 3025	(Type = pos -> arg(16,S,Last);
 3026		(Type = neg -> arg(24,S,Last);
 3027			(Type = rand -> arg(20,S,Last); Last = F))),
 3028        (F1 > Last -> Left = []; Left = [F1-Last]).
 3029find_lazy_left(S,Type,[_|T1],Left):-
 3030        find_lazy_left(S,Type,T1,Left).
 3031
 3032
 3033% prove atoms specified by Type and index set using Clause.
 3034% dependent on data structure used for index set:
 3035% currently index set is a list of intervals
 3036% return atoms proved and their count
 3037% if tail-recursive version is needed see below
 3038
 3039prove(_,_,_,[],[],0,_M).
 3040prove(Flags,Type,Clause,[Interval|Intervals],IList,Count,M):-
 3041	index_prove(Flags,Type,Clause,Interval,I1,C1,M),
 3042	prove(Flags,Type,Clause,Intervals,I2,C2,M),
 3043	aleph_append(I2,I1,IList),
 3044	Count is C1 + C2.
 3045
 3046
 3047%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 3048% T A I L - R E C U R S I V E  P R O V E/6
 3049 
 3050% use this rather than the prove/6 above for tail recursion
 3051% written by James Cussens
 3052 
 3053
 3054% prove(DepthTime,Type,Clause,Intervals,IList,Count,M):-
 3055       % prove2(Intervals,DepthTime,Type,Clause,0,IList,Count,M).
 3056 
 3057% code for tail recursive cover testing
 3058% starts here
 3059
 3060% when we know that Sofar is a variable.
 3061prove2([],_,_,_,Count,[],Count,_M).
 3062prove2([Current-Finish|Intervals],Depth/Time/Proof,Type,(Head:-Body),InCount,Sofar,OutCount,M) :-
 3063	M:example(Current,Type,Example),
 3064	\+ prove1(Proof,Depth/Time,Example,(Head:-Body,M)), %uncovered
 3065        !,
 3066        (Current>=Finish ->
 3067            prove2(Intervals,Depth/Time/Proof,Type,(Head:-Body),InCount,Sofar,OutCount,M);
 3068            Next is Current+1,!,
 3069            prove2([Next-Finish|Intervals],Depth/Time/Proof,Type,(Head:-Body),InCount,Sofar,OutCount,M)
 3070        ).
 3071prove2([Current-Finish|Intervals],ProofFlags,Type,Clause,InCount,Sofar,OutCount,M) :-
 3072        (Current>=Finish ->
 3073            Sofar=[Current-Current|Rest],
 3074            MidCount is InCount+1,!,
 3075            prove2(Intervals,ProofFlags,Type,Clause,MidCount,Rest,OutCount,M);
 3076            Next is Current+1,
 3077            Sofar=[Current-_Last|_Rest],!,
 3078            prove3([Next-Finish|Intervals],ProofFlags,Type,Clause,InCount,Sofar,OutCount,M)
 3079        ).
 3080 
 3081%when Sofar is not a variable
 3082prove3([Current-Finish|Intervals],Depth/Time/Proof,Type,(Head:-Body),InCount,Sofar,OutCount,M) :-
 3083	M:example(Current,Type,Example),
 3084	\+ prove1(Proof,Depth/Time,Example,(Head:-Body),M), %uncovered
 3085        !,
 3086        Last is Current-1, %found some previously
 3087        Sofar=[Start-Last|Rest], %complete found interval
 3088        MidCount is InCount+Current-Start,
 3089        (Current>=Finish ->
 3090            prove2(Intervals,Depth/Time/Proof,Type,(Head:-Body),MidCount,Rest,OutCount,M);
 3091            Next is Current+1,!,
 3092            prove2([Next-Finish|Intervals],Depth/Time/Proof,Type,(Head:-Body),MidCount,Rest,OutCount,M)
 3093        ).
 3094prove3([Current-Finish|Intervals],ProofFlags,Type,Clause,InCount,Sofar,OutCount,M) :-
 3095        (Current>=Finish ->
 3096            Sofar=[Start-Finish|Rest],
 3097            MidCount is InCount+Finish-Start+1,!,
 3098            prove2(Intervals,ProofFlags,Type,Clause,MidCount,Rest,OutCount,M);
 3099            Next is Current+1,!,
 3100            prove3([Next-Finish|Intervals],ProofFlags,Type,Clause,InCount,Sofar,OutCount,M)
 3101        ).
 3102 
 3103 
 3104% code for tail recursive cover testing
 3105% ends here
 3106
 3107index_prove(_,_,_,Start-Finish,[],0,_M):-
 3108	Start > Finish, !.
 3109index_prove(ProofFlags,Type,Clause,Start-Finish,IList,Count,M):-
 3110	index_prove1(ProofFlags,Type,Clause,Start,Finish,Last,M),
 3111	Last0 is Last - 1 ,
 3112	Last1 is Last + 1,
 3113	(Last0 >= Start->
 3114		index_prove(ProofFlags,Type,Clause,Last1-Finish,Rest,Count1,M),
 3115		IList = [Start-Last0|Rest],
 3116		Count is Last - Start + Count1;
 3117		index_prove(ProofFlags,Type,Clause,Last1-Finish,IList,Count,M)).
 3118
 3119prove1(G,M):-
 3120	depth_bound_call(G,M), !.
 3121
 3122prove1(user,_,Example,Clause,M):-
 3123	prove(Clause,Example,M), !.
 3124prove1(restricted_sld,Depth/Time,Example,(Head:-Body),M):-
 3125	\+((\+(((Example = Head),resource_bound_call(Time,Depth,Body,M))))), !.
 3126prove1(sld,Depth/Time,Example,_,M):-
 3127	\+(\+(resource_bound_call(Time,Depth,Example,M))), !.
 3128	
 3129index_prove1(_,_,_,Num,Last,Num,_M):-
 3130	Num > Last, !.
 3131index_prove1(Depth/Time/Proof,Type,Clause,Num,Finish,Last,M):-
 3132	M:example(Num,Type,Example),
 3133	prove1(Proof,Depth/Time,Example,Clause,M), !,
 3134	Num1 is Num + 1,
 3135	index_prove1(Depth/Time/Proof,Type,Clause,Num1,Finish,Last,M).
 3136index_prove1(_,_,_,Last,_,Last,_M).
 3137
 3138
 3139% proves at most Max atoms using Clause.
 3140
 3141prove(_,_,_,_,[],_,[],0,_M).
 3142prove(Flags,ProofFlags,Type,Clause,[Interval|Intervals],Max,IList,Count,M):-
 3143        index_prove(Flags,ProofFlags,Type,Clause,Interval,Max,I1,C1,M), !,
 3144        Max1 is Max - C1,
 3145        prove(Flags,ProofFlags,Type,Clause,Intervals,Max1,I2,C2,M),
 3146        aleph_append(I2,I1,IList),
 3147        Count is C1 + C2.
 3148
 3149
 3150index_prove(_,_,_,_,Start-Finish,_,[],0,_M):-
 3151        Start > Finish, !.
 3152index_prove(Flags,ProofFlags,Type,Clause,Start-Finish,Max,IList,Count,M):-
 3153        index_prove1(Flags,ProofFlags,Type,Clause,Start,Finish,0,Max,Last,M),
 3154        Last0 is Last - 1 ,
 3155        Last1 is Last + 1,
 3156        (Last0 >= Start->
 3157                Max1 is Max - Last + Start,
 3158		((Max1 = 0, Flags = true/_) ->
 3159                        Rest = [], Count1 = 0;
 3160                	index_prove(Flags,ProofFlags,Type,Clause,Last1-Finish,
 3161					Max1,Rest,Count1,M)),
 3162                IList = [Start-Last0|Rest],
 3163                Count is Last - Start + Count1;
 3164                index_prove(Flags,ProofFlags,Type,Clause,Last1-Finish,Max,IList,Count,M)).
 3165
 3166index_prove1(false/_,_,_,_,_,_,Proved,Allowed,_,_M):-
 3167        Proved > Allowed, !, fail.
 3168index_prove1(_,_,_,_,Num,Last,_,_,Num,_M):-
 3169        Num > Last, !.
 3170index_prove1(true/_,_,_,_,Num,_,Allowed,Allowed,Num,_M):- !.
 3171index_prove1(LNegs/Caching,Depth/Time/Proof,Type,Clause,Num,Finish,Proved,Allowed,Last,M):-
 3172	M:example(Num,Type,Example),
 3173	prove1(Proof,Depth/Time,Example,Clause,M), !,
 3174        Num1 is Num + 1,
 3175        Proved1 is Proved + 1,
 3176        (Caching = true ->
 3177                (retract(M:'$aleph_local'(example_cache,L)) ->
 3178                        asserta(M:'$aleph_local'(example_cache,[Num|L]));
 3179                        asserta(M:'$aleph_local'(example_cache,[Num])));
 3180                true),
 3181        index_prove1(LNegs/Caching,Depth/Time/Proof,Type,Clause,Num1,Finish,Proved1,Allowed,Last,M).
 3182index_prove1(_,_,_,_,Last,_,_,_,Last,_M).
 3183
 3184% resource_bound_call(Time,Depth,Goals)
 3185%	attempt to prove Goals using depth bounded theorem-prover
 3186%	in at most Time secs
 3187resource_bound_call(T,Depth,Goals,M):-
 3188	Inf is inf,
 3189	T =:= Inf,
 3190	!,
 3191	depth_bound_call(Goals,Depth,M).
 3192resource_bound_call(T,Depth,Goals,M):-
 3193        catch(time_bound_call(T,prooflimit,depth_bound_call(Goals,Depth,M),M),
 3194		prooflimit,fail).
 3195
 3196time_bound_call(T,Exception,Goal,M):-
 3197	alarm(T,throw(Exception),X),
 3198        (M:Goal -> remove_alarm(X); remove_alarm(X), fail).
 3199
 3200%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 3201% C A C H I N G
 3202
 3203clear_cache(M):-
 3204	retractall(M:'$aleph_search_cache'(_)),
 3205	retractall(M:'$aleph_search_prunecache'(_)).
 3206
 3207check_cache(Entry,Type,I,M):-
 3208	Entry \= false,
 3209        M:'$aleph_search_cache'(Entry), !,
 3210        functor(Entry,_,Arity),
 3211        (Type = pos -> Arg is Arity - 1; Arg is Arity),
 3212        arg(Arg,Entry,I),
 3213	nonvar(I).
 3214
 3215add_cache(false,_,_,_M):- !.
 3216add_cache(Entry,Type,I,M):-
 3217        (retract(M:'$aleph_search_cache'(Entry))-> true ; true),
 3218        functor(Entry,_,Arity),
 3219        (Type = pos -> Arg is Arity - 1; Arg is Arity),
 3220        (arg(Arg,Entry,I)-> asserta(M:'$aleph_search_cache'(Entry));
 3221                        true), !.
 3222
 3223update_cache(Entry,Type,I,M):-
 3224        Entry \= false,
 3225        functor(Entry,Name,Arity),
 3226        (Type = pos -> Arg is Arity - 1; Arg is Arity),
 3227        arg(Arg,Entry,OldI),
 3228        OldI = _/_,
 3229        retract(M:'$aleph_search_cache'(Entry)),
 3230        functor(NewEntry,Name,Arity),
 3231        Arg0 is Arg - 1,
 3232        copy_args(Entry,NewEntry,1,Arg0),
 3233        arg(Arg,NewEntry,I),
 3234        Arg1 is Arg + 1,
 3235        copy_args(Entry,NewEntry,Arg1,Arity),
 3236        asserta(M:'$aleph_search_cache'(NewEntry)), !.
 3237update_cache(_,_,_,_M).
 3238
 3239	
 3240add_prune_cache(false,_M):- !.
 3241add_prune_cache(Entry,M):-
 3242	(M:'$aleph_global'(caching,set(caching,true))->
 3243		functor(Entry,_,Arity),
 3244		A1 is Arity - 2,
 3245		arg(A1,Entry,Clause),
 3246		asserta(M:'$aleph_search_prunecache'(Clause));
 3247		true).
 3248
 3249get_cache_entry(Max,Clause,Entry):-
 3250        skolemize(Clause,Head,Body,0,_),
 3251	length(Body,L1),
 3252	Max >= L1 + 1,
 3253        aleph_hash_term([Head|Body],Entry), !.
 3254get_cache_entry(_,_,false).
 3255
 3256% upto 3-argument indexing using predicate names in a clause
 3257aleph_hash_term([L0,L1,L2,L3,L4|T],Entry):-
 3258        !,
 3259        functor(L1,P1,_), functor(L2,P2,_),
 3260        functor(L3,P3,_), functor(L4,P4,_),
 3261        functor(Entry,P4,6),
 3262        arg(1,Entry,P2), arg(2,Entry,P3),
 3263        arg(3,Entry,P1), arg(4,Entry,[L0,L1,L2,L3,L4|T]).
 3264aleph_hash_term([L0,L1,L2,L3],Entry):-
 3265        !,
 3266        functor(L1,P1,_), functor(L2,P2,_),
 3267        functor(L3,P3,_),
 3268        functor(Entry,P3,5),
 3269        arg(1,Entry,P2), arg(2,Entry,P1),
 3270        arg(3,Entry,[L0,L1,L2,L3]).
 3271aleph_hash_term([L0,L1,L2],Entry):-
 3272        !,
 3273        functor(L1,P1,_), functor(L2,P2,_),
 3274        functor(Entry,P2,4),
 3275        arg(1,Entry,P1), arg(2,Entry,[L0,L1,L2]).
 3276aleph_hash_term([L0,L1],Entry):-
 3277        !,
 3278        functor(L1,P1,_),
 3279        functor(Entry,P1,3),
 3280        arg(1,Entry,[L0,L1]).
 3281aleph_hash_term([L0],Entry):-
 3282        functor(L0,P0,_),
 3283        functor(Entry,P0,3),
 3284        arg(1,Entry,[L0]).
 3285%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 3286% T R E E S
 3287
 3288construct_tree(Type,M):-
 3289	setting(searchtime,Time,M),
 3290	Inf is inf,
 3291        Time =\= Inf,
 3292        SearchTime is integer(Time),
 3293        SearchTime > 0, !,
 3294	catch(time_bound_call(SearchTime,searchlimit,find_tree(Type),M),
 3295		searchlimit,p_message('Time limit reached')).
 3296construct_tree(Type,M):-
 3297	find_tree(Type,M).
 3298
 3299% find_tree(Type,M) where Type is one of
 3300%      classification, regression, class_probability
 3301find_tree(Type,M):-
 3302	retractall(M:'$aleph_search'(tree,_)),
 3303	retractall(M:'$aleph_search'(tree_besterror,_)),
 3304	retractall(M:'$aleph_search'(tree_gain,_)),
 3305	retractall(M:'$aleph_search'(tree_lastleaf,_)),
 3306	retractall(M:'$aleph_search'(tree_leaf,_)),
 3307	retractall(M:'$aleph_search'(tree_newleaf,_)),
 3308	retractall(M:'$aleph_search'(tree_startdistribution,_)),
 3309	get_start_distribution(Type,Distribution,M),
 3310	asserta(M:'$aleph_search'(tree_startdistribution,d(Type,Distribution))),
 3311	M:'$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 3312	setting(dependent,Argno,M),
 3313	p_message('constructing tree'),
 3314	stopwatch(StartClock),
 3315	get_search_settings(S,M),
 3316	auto_refine(aleph_false,Head,M),
 3317	gen_leaf(Leaf,M),
 3318	eval_treenode(S,Type,(Head:-true),[Argno],Pos,Examples,N,Cost,M),
 3319	asserta(M:'$aleph_search'(tree_leaf,l(Leaf,Leaf,[Head,Cost,N],Examples))),
 3320	find_tree1([Leaf],S,Type,[Argno],M),
 3321	prune_rules(S,Type,[Argno],M),
 3322	stopwatch(StopClock),
 3323	add_tree(S,Type,[Argno],M),
 3324	Time is StopClock - StartClock,
 3325	p1_message('construction time'), p_message(Time).
 3326
 3327get_start_distribution(regression,0-[0,0],_M):- !.
 3328get_start_distribution(model,0-[0,0],M):-
 3329	setting(evalfn,mse,M), !.
 3330get_start_distribution(model,0-Distribution,M):- 
 3331	setting(evalfn,accuracy,M), !,
 3332	(setting(classes,Classes,M) -> true;
 3333		!,
 3334		p_message('missing setting for classes'),
 3335		fail),
 3336	initialise_distribution(Classes,Distribution), !.
 3337get_start_distribution(Tree,0-Distribution,M):-
 3338	(Tree = classification; Tree = class_probability),
 3339	(setting(classes,Classes,M) -> true;
 3340		!,
 3341		p_message('missing setting for classes'),
 3342		fail),
 3343	initialise_distribution(Classes,Distribution), !.
 3344get_start_distribution(_,_,_M):-
 3345	p_message('incorrect/missing setting for tree_type or evalfn'),
 3346	fail.
 3347
 3348initialise_distribution([],[]).
 3349initialise_distribution([Class|Classes],[0-Class|T]):-
 3350	initialise_distribution(Classes,T).
 3351
 3352laplace_correct([],[]).
 3353laplace_correct([N-Class|Classes],[N1-Class|T]):-
 3354	N1 is N + 1,
 3355	laplace_correct(Classes,T).
 3356
 3357find_tree1([],_,_,_,_M).
 3358find_tree1([Leaf|Leaves],S,Type,Predict,M):-
 3359	can_split(S,Type,Predict,Leaf,Left,Right,M), !,
 3360	split_leaf(Leaf,Left,Right,NewLeaves,M),
 3361	aleph_append(NewLeaves,Leaves,LeavesLeft),
 3362	find_tree1(LeavesLeft,S,Type,Predict,M).
 3363find_tree1([_|LeavesLeft],S,Type,Predict,M):-
 3364	find_tree1(LeavesLeft,S,Type,Predict,M).
 3365
 3366prune_rules(S,Tree,Predict,M):-
 3367	setting(prune_tree,true,M), 
 3368	prune_rules1(Tree,S,Predict,M), !.
 3369prune_rules(_,_,_,_M).
 3370
 3371% pessimistic pruning by employing corrections to observed errors
 3372prune_rules1(class_probability,_,_,_M):-
 3373	p_message('no pruning for class probability trees'), !.
 3374prune_rules1(model,_,_,_M):-
 3375	p_message('no pruning for model trees'), !.
 3376prune_rules1(Tree,S,Predict,M):-
 3377	p_message('pruning clauses'),
 3378	M:'$aleph_search'(tree_leaf,l(Leaf,Parent,Clause,Examples)),
 3379	prune_rule(Tree,S,Predict,Clause,Examples,NewClause,NewExamples,M),
 3380	retract(M:'$aleph_search'(tree_leaf,l(Leaf,Parent,Clause,Examples))),
 3381	asserta(M:'$aleph_search'(tree_newleaf,l(Leaf,Parent,NewClause,NewExamples))),
 3382	fail.
 3383prune_rules1(_,_,_,M):-
 3384	retract(M:'$aleph_search'(tree_newleaf,l(Leaf,Parent,NewClause,NewExamples))),
 3385	asserta(M:'$aleph_search'(tree_leaf,l(Leaf,Parent,NewClause,NewExamples))),
 3386	fail.
 3387prune_rules1(_,_,_,_M).
 3388
 3389prune_rule(Tree,S,PredictArg,[Clause,_,N],Examples,[PrunedClause,E1,NCov],NewEx,M):-
 3390	node_stats(Tree,Examples,PredictArg,Total-Distribution,M),
 3391	leaf_prediction(Tree,Total-Distribution,_,Incorrect),
 3392	estimate_error(Tree,Incorrect,Total,Upper,M),
 3393	split_clause(Clause,Head,Body),
 3394	goals_to_list(Body,BodyL),
 3395	arg(14,S,Depth),
 3396	arg(29,S,Time),
 3397	arg(34,S,Proof),
 3398	greedy_prune_rule(Tree,Depth/Time/Proof,PredictArg,[Head|BodyL],Upper,C1L,E1,M),
 3399	list_to_clause(C1L,PrunedClause),
 3400	% p1_message('pruned clause'), p_message(Clause),
 3401	% p_message('to'),
 3402	% p_message(PrunedClause),
 3403	(E1 < Upper ->
 3404		M:'$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 3405        	prove(Depth/Time/Proof,pos,PrunedClause,Pos,NewEx,NCov,M);
 3406		NewEx = Examples,
 3407		NCov = N).
 3408
 3409
 3410% estimate error using binomial distribution as done in C4.5
 3411estimate_error(classification,Incorrect,Total,Error,M):-
 3412	setting(confidence,Conf,M),
 3413	estimate_error(1.0/0.0,0.0/1.0,Conf,Total,Incorrect,Error).
 3414
 3415% estimate upper bound on sample std deviation by
 3416% assuming the n values in a leaf are normally distributed.
 3417% In this case, a (1-alpha)x100 confidence interval for the
 3418% variance is (n-1)s^2/X^2(alpha/2) =< var =< (n-1)s^2/X^2(1-alpha/2)
 3419estimate_error(regression,Sd,1,Sd,_M):- !.
 3420estimate_error(regression,Sd,N,Upper,M):-
 3421	(setting(confidence,Conf,M) -> true; Conf = 0.95),
 3422	Alpha is 1.0 - Conf,
 3423	DF is N - 1,
 3424	Prob is 1 - Alpha/2,
 3425	chi_square(DF,Prob,ChiSq),
 3426	Upper is Sd*sqrt((N-1)/ChiSq).
 3427
 3428bound_error(classification,Error,Total,Lower,Upper,M):-
 3429	(setting(confidence,Alpha,M) -> true; Alpha = 0.95),
 3430	approx_z(Alpha,Z),
 3431	Lower is Error - Z*sqrt(Error*(1-Error)/Total),
 3432	Upper is Error + Z*sqrt(Error*(1-Error)/Total).
 3433
 3434approx_z(P,2.58):- P >= 0.99, !.
 3435approx_z(P,Z):- P >= 0.98, !, Z is 2.33 + (P-0.98)*(2.58-2.33)/(0.99-0.98).
 3436approx_z(P,Z):- P >= 0.95, !, Z is 1.96 + (P-0.95)*(2.33-1.96)/(0.98-0.95).
 3437approx_z(P,Z):- P >= 0.90, !, Z is 1.64 + (P-0.90)*(1.96-1.64)/(0.95-0.90).
 3438approx_z(P,Z):- P >= 0.80, !, Z is 1.28 + (P-0.80)*(1.64-1.28)/(0.90-0.80).
 3439approx_z(P,Z):- P >= 0.68, !, Z is 1.00 + (P-0.68)*(1.28-1.00)/(0.80-0.68).
 3440approx_z(P,Z):- P >= 0.50, !, Z is 0.67 + (P-0.50)*(1.00-0.67)/(0.68-0.50).
 3441approx_z(_,0.67).
 3442
 3443greedy_prune_rule(Tree,Flags,PredictArg,Clause,Err0,NewClause,BestErr,M):-
 3444	greedy_prune_rule1(Tree,Flags,PredictArg,Clause,Err0,Clause1,Err1,M),
 3445	Clause \= Clause1, !,
 3446	greedy_prune_rule(Tree,Flags,PredictArg,Clause1,Err1,NewClause,BestErr,M).
 3447greedy_prune_rule(_,_,_,C,E,C,E,_M).
 3448
 3449
 3450greedy_prune_rule1(Tree,Flags,PredictArg,[Head|Body],Err0,_,_,M):-
 3451	retractall(M:'$aleph_search'(tree_besterror,_)),
 3452	asserta(M:'$aleph_search'(tree_besterror,besterror([Head|Body],Err0))),
 3453	M:'$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 3454	aleph_delete(_,Body,Left),
 3455	strip_negs(Left,Body1),
 3456	aleph_mode_linked([Head|Body1],M),
 3457	list_to_clause([Head|Left],Clause),
 3458        prove(Flags,pos,Clause,Pos,Ex1,_,M),
 3459	node_stats(Tree,Ex1,PredictArg,Total-Distribution,M),
 3460	leaf_prediction(Tree,Total-Distribution,_,Incorrect),
 3461	estimate_error(Tree,Incorrect,Total,Upper,M),
 3462	M:'$aleph_search'(tree_besterror,besterror(_,BestError)),
 3463	Upper =< BestError, 
 3464	retract(M:'$aleph_search'(tree_besterror,besterror(_,BestError))),
 3465	asserta(M:'$aleph_search'(tree_besterror,besterror([Head|Left],Upper))),
 3466	fail.
 3467greedy_prune_rule1(_,_,_,_,_,Clause1,Err1,M):-
 3468	retract(M:'$aleph_search'(tree_besterror,besterror(Clause1,Err1))).
 3469
 3470strip_negs([],[]).
 3471strip_negs([not(L)|T],[L|T1]):-
 3472	!,
 3473	strip_negs(T,T1).
 3474strip_negs([L|T],[L|T1]):-
 3475	strip_negs(T,T1).
 3476	
 3477add_tree(_,Tree,Predict,M):-
 3478	retract(M:'$aleph_search'(tree_leaf,l(_,_,Leaf,Examples))),
 3479	Leaf = [Clause,Cost,P],
 3480	add_prediction(Tree,Clause,Predict,Examples,Clause1,M),
 3481	p_message('best clause'),
 3482	pp_dclause(Clause1,M),
 3483        nlits(Clause,L),
 3484	Gain is -Cost,
 3485        asserta(M:'$aleph_global'(hypothesis,hypothesis([P,0,L,Gain],Clause1,Examples,[]))),
 3486	addhyp(M),
 3487	fail.
 3488add_tree(_,_,_,_M).
 3489
 3490add_prediction(Tree,Clause,PredictArg,Examples,Clause1,M):-
 3491	split_clause(Clause,Head,_),
 3492	(Tree = model ->
 3493		setting(evalfn,Evalfn,M),
 3494		add_model(Evalfn,Clause,PredictArg,Examples,Clause1,_,_,M);
 3495		node_stats(Tree,Examples,PredictArg,Distribution,M),
 3496		leaf_prediction(Tree,Distribution,Prediction,Error),
 3497		tparg(PredictArg,Head,Var),
 3498		add_prediction(Tree,Clause,Var,Prediction,Error,Clause1,M)).
 3499
 3500add_prediction(classification,Clause,Var,Prediction,_,Clause1,_M):-
 3501	extend_clause(Clause,(Var = Prediction),Clause1).
 3502add_prediction(class_probability,Clause,Var,Prediction,_,Clause1,_M):-
 3503	extend_clause(Clause,(random(Var,Prediction)),Clause1).
 3504add_prediction(regression,Clause,Var,Mean,Sd,Clause1,_M):-
 3505	extend_clause(Clause,(random(Var,normal(Mean,Sd))),Clause1).
 3506
 3507add_model(Evalfn,Clause,PredictArg,Examples,_,_,_,M):-
 3508	retractall(M:'$aleph_local'(tree_model,_,_,_)),
 3509	Best is inf,
 3510	split_clause(Clause,Head,_),
 3511	tparg(PredictArg,Head,Var),
 3512	asserta(M:'$aleph_local'(tree_model,aleph_false,0,Best)),
 3513	M:'$aleph_global'(model,model(Name/Arity)),
 3514	functor(Model,Name,Arity),
 3515	auto_extend(Clause,Model,C,M),
 3516	leaf_predicts(Arity,Model,Var),
 3517	lazy_evaluate_refinement([],C,[Name/Arity],Examples,[],[],C1,M),
 3518	find_model_error(Evalfn,Examples,C1,PredictArg,Total,Error,M),
 3519	% pp_dclause(C1,M),
 3520	% p1_message(error),
 3521	% p1_message(Error),
 3522	M:'$aleph_local'(tree_model,_,_,BestSoFar),
 3523	%p1_message(BestSoFar),
 3524	(Error < BestSoFar ->
 3525		retract(M:'$aleph_local'(tree_model,_,_,_)),
 3526		asserta(M:'$aleph_local'(tree_model,C1,Total,Error));
 3527		true),
 3528	fail.	
 3529add_model(_,_,_,_,Clause,Total,Error,M):-
 3530	retract(M:'$aleph_local'(tree_model,Clause,Total,Error)).
 3531
 3532
 3533find_model_error(Evalfn,Examples,(Head:-Body),[PredictArg],T,E,M):-
 3534	functor(Head,_,Arity),
 3535	findall(Actual-Pred,
 3536			(aleph_member(Interval,Examples),
 3537			aleph_member3(N,Interval),
 3538			M:example(N,pos,Example),
 3539			copy_iargs(Arity,Example,Head,PredictArg),
 3540			once(M:Body),
 3541			arg(PredictArg,Head,Pred), 
 3542			arg(PredictArg,Example,Actual)
 3543			), 
 3544		L),
 3545	sum_model_errors(L,Evalfn,0,0.0,T,E), !.
 3546
 3547sum_model_errors([],_,N,E,N,E).
 3548sum_model_errors([Act-Pred|T],Evalfn,NSoFar,ESoFar,N,E):-
 3549	get_model_error(Evalfn,Act,Pred,E1),
 3550	E1SoFar is ESoFar + E1,
 3551	N1SoFar is NSoFar + 1,
 3552	sum_model_errors(T,Evalfn,N1SoFar,E1SoFar,N,E).
 3553
 3554get_model_error(mse,Act,Pred,E):-
 3555	E is (Act-Pred)^2.
 3556get_model_error(accuracy,Act,Pred,E):-
 3557	(Act = Pred -> E is 0.0; E is 1.0).
 3558
 3559leaf_predicts(0,_,_):- !, fail.
 3560leaf_predicts(Arg,Model,Var):-
 3561	arg(Arg,Model,Var1),
 3562	var(Var1),
 3563	Var1 == Var, !.
 3564leaf_predicts(Arg,Model,Var):-
 3565	Arg1 is Arg - 1,
 3566	leaf_predicts(Arg1,Model,Var).
 3567	
 3568leaf_prediction(classification,Total-Distribution,Class,Incorrect):-
 3569	find_maj_class(Distribution,N-Class),
 3570	Incorrect is Total - N.
 3571leaf_prediction(class_probability,T1-D1,NDistr,0):-
 3572	length(D1,NClasses),
 3573	laplace_correct(D1,LaplaceD1),
 3574	LaplaceTotal is T1 + NClasses,
 3575	normalise_distribution(LaplaceD1,LaplaceTotal,NDistr).
 3576leaf_prediction(regression,_-[Mean,Sd],Mean,Sd).
 3577
 3578find_maj_class([X],X):- !.
 3579find_maj_class([N-Class|Rest],MajClass):-
 3580	find_maj_class(Rest,N1-C1),
 3581	(N > N1 -> MajClass = N-Class; MajClass = N1-C1).
 3582
 3583can_split(S,Type,Predict,Leaf,Left,Right,M):-
 3584	arg(21,S,MinGain),
 3585	M:'$aleph_search'(tree_leaf,l(Leaf,_,[Clause,Cost,N],Examples)),
 3586	Cost >= MinGain, 
 3587	get_best_subtree(S,Type,Predict,[Clause,Cost,N],Examples,Gain,Left,Right,M),
 3588	Gain >= MinGain,
 3589	p_message('found clauses'),
 3590	Left = [ClF,CostF|_], Right = [ClS,CostS|_],
 3591	arg(4,S,_/Evalfn),
 3592	pp_dclause(ClS,M),
 3593	print_eval(Evalfn,CostS),
 3594	pp_dclause(ClF,M),
 3595	print_eval(Evalfn,CostF),
 3596	p1_message('expected cost reduction'), p_message(Gain).
 3597
 3598get_best_subtree(S,Type,Predict,[Clause,Cost,N],Examples,Gain,Left,Right,M):-
 3599	arg(42,S,Interactive),
 3600	arg(43,S,LookAhead),
 3601	retractall(M:'$aleph_search'(tree_gain,_)),
 3602	MInf is -inf,
 3603	(Interactive = false ->
 3604		asserta(M:'$aleph_search'(tree_gain,tree_gain(MInf,[],[])));
 3605		true),
 3606	split_clause(Clause,Head,Body),
 3607	arg(4,S,_/Evalfn),
 3608	arg(13,S,MinPos),
 3609	auto_refine(LookAhead,Clause,ClS,M),
 3610	tree_refine_ok(Type,ClS,M),
 3611	eval_treenode(S,Type,ClS,Predict,Examples,ExS,NS,CostS,M),
 3612	NS >= MinPos,
 3613	rm_intervals(ExS,Examples,ExF),
 3614	split_clause(ClS,Head,Body1),
 3615	get_goaldiffs(Body,Body1,Diff),
 3616	extend_clause(Clause,not(Diff),ClF),
 3617	eval_treenode(S,Type,ClF,Predict,ExF,NF,CostF,M),
 3618	NF >= MinPos,
 3619	AvLeafCost is (NS*CostS + NF*CostF)/N,
 3620	CostReduction is Cost - AvLeafCost,
 3621	(Interactive = false ->
 3622		pp_dclause(ClS,M), print_eval(Evalfn,CostS),
 3623		pp_dclause(ClF,M), print_eval(Evalfn,CostF),
 3624		p1_message('expected cost reduction'), p_message(CostReduction),
 3625		M:'$aleph_search'(tree_gain,tree_gain(BestSoFar,_,_)),
 3626		CostReduction > BestSoFar,
 3627		retract(M:'$aleph_search'(tree_gain,tree_gain(BestSoFar,_,_))),
 3628		asserta(M:'$aleph_search'(tree_gain,tree_gain(CostReduction,
 3629							[ClF,CostF,NF,ExF],
 3630							[ClS,CostS,NS,ExS])));
 3631		asserta(M:'$aleph_search'(tree_gain,tree_gain(CostReduction,
 3632							[ClF,CostF,NF,ExF],
 3633							[ClS,CostS,NS,ExS])))),
 3634
 3635	AvLeafCost =< 0.0, 
 3636	!,
 3637	get_best_subtree(Interactive,Clause,Gain,Left,Right,M).
 3638get_best_subtree(S,_,_,[Clause|_],_,Gain,Left,Right,M):-
 3639	arg(42,S,Interactive),
 3640	get_best_subtree(Interactive,Clause,Gain,Left,Right,M).
 3641
 3642get_best_subtree(false,_,Gain,Left,Right,M):-
 3643	retract(M:'$aleph_search'(tree_gain,tree_gain(Gain,Left,Right))), !.
 3644get_best_subtree(true,Clause,Gain,Left,Right,M):-
 3645	nl, write('Extending path: '), nl,
 3646	write('---------------'), nl,
 3647	pp_dclause(Clause,M),
 3648	findall(MCR-[Left,Right],
 3649		(M:'$aleph_search'(tree_gain,tree_gain(CostReduction,Left,Right)), 
 3650		  MCR is -1*CostReduction), 
 3651		SplitsList),
 3652	keysort(SplitsList,Sorted),
 3653	get_best_split(Clause,Sorted,Gain,Left,Right),
 3654	retractall(M:'$aleph_search'(tree_gain,_)).
 3655
 3656get_best_split(Clause,Splits,Gain,Left,Right):-
 3657	show_split_list(Clause,Splits),
 3658	ask_best_split(Splits,Gain,Left,Right).
 3659
 3660show_split_list(Clause,Splits):-
 3661	tab(4), write('Split Information'), nl,
 3662	tab(4), write('-----------------'), nl, nl,
 3663	tab(4), write('No.'), 
 3664	tab(4), write('Split'), 
 3665	nl,
 3666	tab(4), write('---'), 
 3667	tab(4), write('-----'), 
 3668	nl,
 3669	show_split_list(Splits,1,Clause).
 3670
 3671show_split_list([],_,_).
 3672show_split_list([MCR-[[_,_,NF,_],[CLS,_,NS,_]]|Rest],SplitNum,Clause):-
 3673	copy_term(Clause,ClauseCopy),
 3674	split_clause(ClauseCopy,Head,Body),
 3675	copy_term(CLS,CLSCopy),
 3676	numbervars(CLSCopy,0,_),
 3677	split_clause(CLSCopy,Head,Body1),
 3678	get_goaldiffs(Body,Body1,Diff),
 3679	Gain is -1*MCR,
 3680	tab(4), write(SplitNum),
 3681	tab(4), write(Diff), nl,
 3682	tab(12), write('Succeeded (Right Branch): '), write(NS), nl,
 3683	tab(12), write('Failed    (Left Branch) : '), write(NF), nl,
 3684	tab(12), write('Cost Reduction          : '), write(Gain), nl, nl,
 3685	NextSplit is SplitNum + 1,
 3686	show_split_list(Rest,NextSplit,Clause).
 3687
 3688ask_best_split(Splits,Gain,Left,Right):-
 3689	repeat,
 3690	tab(4), write('-> '),
 3691	write('Select Split Number (or "none.")'), nl,
 3692	read(Answer),
 3693	(Answer = none ->
 3694		Gain is -inf,
 3695		Left = [],
 3696		Right = [];
 3697		SplitNum is integer(Answer),
 3698		aleph_remove_nth(SplitNum,Splits,MCR-[Left,Right],_),
 3699		Gain is -1*MCR
 3700	),
 3701	!.
 3702
 3703tree_refine_ok(model,Clause,M):-
 3704        M:'$aleph_global'(model,model(Name/Arity)),
 3705	functor(Model,Name,Arity),
 3706	in(Clause,Model,M), !,
 3707	fail.
 3708tree_refine_ok(_,_,_M).
 3709
 3710
 3711eval_treenode(S,Tree,Clause,PredictArg,PCov,N,Cost,M):-
 3712	arg(4,S,_/Evalfn),
 3713	treenode_cost(Tree,Evalfn,Clause,PCov,PredictArg,N,Cost,M).
 3714
 3715eval_treenode(S,Tree,Clause,PredictArg,Pos,PCov,N,Cost,M):-
 3716	arg(4,S,_/Evalfn),
 3717	arg(13,S,MinPos),
 3718	arg(14,S,Depth),
 3719	arg(29,S,Time),
 3720	arg(34,S,Proof),
 3721        prove(Depth/Time/Proof,pos,Clause,Pos,PCov,PCount,M),
 3722	PCount >= MinPos,
 3723	treenode_cost(Tree,Evalfn,Clause,PCov,PredictArg,N,Cost,M).
 3724
 3725treenode_cost(model,Evalfn,Clause,Covered,PredictArg,Total,Cost,M):-
 3726	!,
 3727	add_model(Evalfn,Clause,PredictArg,Covered,_,Total,Cost,M).
 3728treenode_cost(Tree,Evalfn,_,Covered,PredictArg,Total,Cost,M):-
 3729	node_stats(Tree,Covered,PredictArg,Total-Distribution,M),
 3730	Total > 0,
 3731	impurity(Tree,Evalfn,Total-Distribution,Cost).
 3732
 3733node_stats(Tree,Covered,PredictArg,D,M):-
 3734        M:'$aleph_search'(tree_startdistribution,d(Tree,D0)),
 3735        (Tree = regression ->
 3736                cont_distribution(Covered,PredictArg,D0,D,M);
 3737                discr_distribution(Covered,PredictArg,D0,D,M)).
 3738
 3739discr_distribution([],_,D,D,_M).
 3740discr_distribution([S-F|Intervals],PredictArg,T0-D0,D,M):-
 3741	discr_distribution(S,F,PredictArg,T0-D0,T1-D1,M),
 3742	discr_distribution(Intervals,PredictArg,T1-D1,D,M).
 3743
 3744discr_distribution(N,F,_,D,D,_M):- N > F, !.
 3745discr_distribution(N,F,PredictArg,T0-D0,D,M):-
 3746	M:example(N,pos,Example),
 3747	tparg(PredictArg,Example,Actual),
 3748	N1 is N + 1,
 3749	T1 is T0 + 1,
 3750	(aleph_delete(C0-Actual,D0,D1) ->
 3751		C1 is C0 + 1,
 3752		discr_distribution(N1,F,PredictArg,T1-[C1-Actual|D1],D,M);
 3753		discr_distribution(N1,F,PredictArg,T1-[1-Actual|D0],D,M)).
 3754
 3755cont_distribution([],_,T-[S,SS],T-[Mean,Sd],_M):-
 3756	(T = 0 -> Mean = 0, Sd = 0;
 3757		Mean is S/T,
 3758		Sd is sqrt(SS/T - Mean*Mean)).
 3759cont_distribution([S-F|Intervals],PredictArg,T0-D0,D,M):-
 3760        cont_distribution(S,F,PredictArg,T0-D0,T1-D1,M),
 3761        cont_distribution(Intervals,PredictArg,T1-D1,D,M).
 3762
 3763cont_distribution(N,F,_,D,D,_M):- N > F, !.
 3764cont_distribution(N,F,PredictArg,T0-[S0,SS0],D,M):-
 3765        M:example(N,pos,Example),
 3766        tparg(PredictArg,Example,Actual),
 3767	N1 is N + 1,
 3768        T1 is T0 + 1,
 3769	S1 is S0 + Actual,
 3770	SS1 is SS0 + Actual*Actual,
 3771        cont_distribution(N1,F,PredictArg,T1-[S1,SS1],D,M).
 3772
 3773impurity(regression,sd,_-[_,Sd],Sd):- !.
 3774impurity(classification,entropy,Total-Distribution,Cost):-
 3775	sum_entropy(Distribution,Total,S),
 3776	Cost is -S/(Total*log(2)), !.
 3777impurity(classification,gini,Total-Distribution,Cost):-
 3778	sum_gini(Distribution,Total,Cost), !.
 3779impurity(class_probability,entropy,Total-Distribution,Cost):-
 3780	sum_entropy(Distribution,Total,S),
 3781	Cost is -S/(Total*log(2)), !.
 3782impurity(class_probability,gini,Total-Distribution,Cost):-
 3783	sum_gini(Distribution,Total,Cost), !.
 3784impurity(_,_,_,_):-
 3785	err_message('inappropriate settings for tree_type and/or evalfn'),
 3786	fail.
 3787
 3788
 3789sum_gini([],_,0).
 3790sum_gini([N-_|Rest],Total,Sum):-
 3791	N > 0, !,
 3792	sum_gini(Rest,Total,C0),
 3793	P is N/Total,
 3794	Sum is P*(1-P) + C0.
 3795sum_gini([_|Rest],Total,Sum):-
 3796	sum_gini(Rest,Total,Sum).
 3797
 3798sum_entropy([],_,0).
 3799sum_entropy([N-_|Rest],Total,Sum):-
 3800	N > 0, !,
 3801	sum_entropy(Rest,Total,C0),
 3802	Sum is N*log(N/Total) + C0.
 3803sum_entropy([_|Rest],Total,Sum):-
 3804	sum_entropy(Rest,Total,Sum).
 3805
 3806% only binary splits
 3807% left = condition at node fails
 3808% right = condition at node succeeds
 3809split_leaf(Leaf,LeftTree,RightTree,[Left,Right],M):-
 3810	retract(M:'$aleph_search'(tree_leaf,l(Leaf,Parent,
 3811						[Clause,Cost,N],Examples))),
 3812	gen_leaf(Left,M),
 3813	gen_leaf(Right,M),
 3814	LeftTree = [ClF,CostF,NF,ExF],
 3815	RightTree = [ClS,CostS,NS,ExS],
 3816	asserta(M:'$aleph_search'(tree,t(Leaf,Parent,[Clause,Cost,N],
 3817					Examples,Left,Right))),
 3818	asserta(M:'$aleph_search'(tree_leaf,l(Left,Leaf,[ClF,CostF,NF],ExF))),
 3819	asserta(M:'$aleph_search'(tree_leaf,l(Right,Leaf,[ClS,CostS,NS],ExS))).
 3820
 3821gen_leaf(Leaf1,M):-
 3822	retract(M:'$aleph_search'(tree_lastleaf,Leaf0)), !,
 3823	Leaf1 is Leaf0 + 1,
 3824	asserta(M:'$aleph_search'(tree_lastleaf,Leaf1)).
 3825gen_leaf(0,M):-
 3826        asserta(M:'$aleph_search'(tree_lastleaf,0)).
 3827
 3828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 3829% G C W S
 3830
 3831% examine list of clauses to be specialised
 3832% generate an exception theory for each clause that covers negative examples
 3833gcws(M):-
 3834	setting(evalfn,EvalFn,M),
 3835	repeat,
 3836	retract(M:'$aleph_search'(sphyp,hypothesis([P,N,L|T],Clause,PCover,NCover))),
 3837	(PCover = _/_ -> label_create(pos,Clause,Label1,M),
 3838		extract_pos(Label1,PCover1),
 3839		interval_count(PCover1,P1);
 3840		PCover1 = PCover,
 3841		P1 = P),
 3842	(NCover = _/_ -> label_create(neg,Clause,Label2,M),
 3843		extract_neg(Label2,NCover1),
 3844		interval_count(NCover1,N1);
 3845		NCover1 = NCover,
 3846		N1 = N),
 3847	(N1 = 0 -> NewClause = Clause, NewLabel = [P1,N1,L|T];
 3848		MinAcc is P1/(2*P1 - 1),
 3849		set(minacc,MinAcc,M),
 3850		set(noise,N1,M),
 3851		gcws(Clause,PCover1,NCover1,NewClause,M),
 3852		L1 is L + 1,
 3853		complete_label(EvalFn,NewClause,[P,0,L1],NewLabel,M)),
 3854	assertz(M:'$aleph_search'(gcwshyp,hypothesis(NewLabel,NewClause,PCover1,[]))),
 3855	\+(M:'$aleph_search'(sphyp,hypothesis(_,_,_,_))), !.
 3856
 3857
 3858% gcws(+Clause,+PCvr,+NCvr,-Clause1)
 3859%	specialise Clause that covers pos examples PCvr and neg examples NCvr
 3860%	result is is Clause extended with a single negated literal
 3861% clauses in exception theory are added to list for specialisation
 3862gcws(Clause,PCover,NCover,Clause1,M):-
 3863	gen_absym(AbName,M),
 3864	split_clause(Clause,Head,Body),
 3865	functor(Head,_,Arity),
 3866	add_determinations(AbName/Arity,true,M),
 3867	add_modes(AbName/Arity,M),
 3868	gen_ab_examples(AbName/Arity,PCover,NCover,M),
 3869	cwinduce(M),
 3870	Head =.. [_|Args],
 3871	AbLit =.. [AbName|Args],
 3872	(Body = true -> Body1 = not(AbLit) ; app_lit(not(AbLit),Body,Body1)),
 3873	Clause1 = (Head:-Body1).
 3874
 3875% greedy set-cover based construction of abnormality theory 
 3876% starts with the first exceptional example
 3877% each clause obtained is added to list of clauses to be specialised 
 3878cwinduce(M):-
 3879	store(greedy,M),
 3880        set(greedy,true,M),
 3881        M:'$aleph_global'(atoms_left,atoms_left(pos,PosSet)),
 3882        PosSet \= [],
 3883        repeat,
 3884	M:'$aleph_global'(atoms_left,atoms_left(pos,[Num-X|Y])),
 3885	sat(Num,M),
 3886	reduce(M:_),
 3887	retract(M:'$aleph_global'(hypothesis,hypothesis(Label,H,PCover,NCover))),
 3888	asserta(M:'$aleph_search'(sphyp,hypothesis(Label,H,PCover,NCover))),
 3889        rm_seeds1(PCover,[Num-X|Y],NewPosLeft),
 3890	retract(M:'$aleph_global'(atoms_left,atoms_left(pos,[Num-X|Y]))),
 3891        asserta(M:'$aleph_global'(atoms_left,atoms_left(pos,NewPosLeft))),
 3892	NewPosLeft = [],
 3893        retract(M:'$aleph_global'(atoms_left,atoms_left(pos,NewPosLeft))),
 3894	reinstate(greedy,M), !.
 3895cwinduce(_M).
 3896
 3897
 3898% gen_ab_examples(+Ab,+PCover,+NCover)
 3899% obtain examples for abnormality predicate Ab by
 3900%	pos examples are copies of neg examples in NCover
 3901%	neg examples are copies of pos examples in PCover
 3902% writes new examples to temporary ".f" and ".n" files
 3903% to ensure example/3 remains a static predicate
 3904% alters search parameters accordingly
 3905gen_ab_examples(Ab/_,PCover,NCover,M):-
 3906	create_examples(PosFile,Ab,neg,NCover,pos,PCover1,M),
 3907	create_examples(NegFile,Ab,pos,PCover,neg,NCover1,M),
 3908	aleph_consult(PosFile,M),
 3909	aleph_consult(NegFile,M),
 3910        retractall(M:'$aleph_global'(atoms_left,_)),
 3911        retractall(M:'$aleph_global'(size,_)),
 3912        asserta(M:'$aleph_global'(atoms_left,atoms_left(pos,PCover1))),
 3913        asserta(M:'$aleph_global'(atoms_left,atoms_left(neg,NCover1))),
 3914        interval_count(PCover1,PSize),
 3915        interval_count(NCover1,NSize),
 3916        asserta(M:'$aleph_global'(size,size(pos,PSize))),
 3917        asserta(M:'$aleph_global'(size,size(neg,NSize))),
 3918	delete_file(PosFile),
 3919	delete_file(NegFile).
 3920
 3921% create_examples(+File,+OldType,+OldE,+NewType,-NewE)
 3922% copy OldE examples of OldType to give NewE examples of NewType 
 3923% copy stored in File
 3924create_examples(File,Ab,OldT,OldE,NewT,[Next-Last],M):-
 3925        tmp_file_stream(utf8,File,Stream),
 3926	M:'$aleph_global'(last_example,last_example(NewT,OldLast)),
 3927	set_output(Stream),
 3928	create_copy(OldE,OldT,NewT,Ab,OldLast,Last,M),
 3929	close(Stream),
 3930	set_output(user_output),
 3931	Last > OldLast, !,
 3932	retract(M:'$aleph_global'(last_example,last_example(NewT,OldLast))),
 3933	Next is OldLast + 1,
 3934	asserta(M:'$aleph_global'(last_example,last_example(NewT,Last))).
 3935create_examples(_,_,_,_,_,[],_M).
 3936
 3937create_copy([],_,_,_,L,L,_M).
 3938create_copy([X-Y|T],OldT,NewT,Ab,Num,Last,M):-
 3939	create_copy(X,Y,OldT,NewT,Ab,Num,Num1,M),
 3940	create_copy(T,OldT,NewT,Ab,Num1,Last,M).
 3941
 3942create_copy(X,Y,_,_,_,L,L,_M):- X > Y, !.
 3943create_copy(X,Y,OldT,NewT,Ab,Num,Last,M):-
 3944	M:example(X,OldT,Example),
 3945	Example =.. [_|Args],
 3946	NewExample =.. [Ab|Args],
 3947	Num1 is Num + 1,
 3948	aleph_writeq(example(Num1,NewT,NewExample)), write('.'), nl,
 3949	X1 is X + 1,
 3950	create_copy(X1,Y,OldT,NewT,Ab,Num1,Last,M).
 3951
 3952% gen_absym(-Name)
 3953% generate new abnormality predicate symbol
 3954gen_absym(Name,M):-
 3955	(retract(M:'$aleph_global'(last_ab,last_ab(N))) ->
 3956		N1 is N + 1;
 3957		N1 is 0),
 3958	asserta(M:'$aleph_global'(last_ab,last_ab(N1))),
 3959	concat([ab,N1],Name).
 3960%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 3961% C L A U S E   O P T I M I S A T I O N S
 3962
 3963
 3964optimise(Clause,Clause1):-
 3965	remove_redundant(Clause,Clause0),
 3966	reorder_clause(Clause0,Clause1).
 3967
 3968remove_redundant((Head:-Body),(Head1:-Body1)):-
 3969	goals_to_list((Head,Body),ClauseL),
 3970	remove_subsumed(ClauseL,[Head1|Body1L]),
 3971	(Body1L = [] -> Body1 = true; list_to_goals(Body1L,Body1)).
 3972
 3973reorder_clause((Head:-Body), Clause) :-
 3974        % term_variables(Head,LHead),
 3975        vars_in_term([Head],[],LHead),
 3976        number_goals_and_get_vars(Body,LHead,1,_,[],Conj),
 3977        calculate_independent_sets(Conj,[],BSets),
 3978        compile_clause(BSets,Head,Clause).
 3979
 3980number_goals_and_get_vars((G,Body),LHead,I0,IF,L0,[g(I0,LVF,NG)|LGs]) :- !,
 3981        I is I0+1,
 3982        get_goal_vars(G,LHead,LVF,NG),
 3983        number_goals_and_get_vars(Body,LHead,I,IF,L0,LGs).
 3984number_goals_and_get_vars(G,LHead,I,I,L0,[g(I,LVF,NG)|L0]) :-
 3985        get_goal_vars(G,LHead,LVF,NG).
 3986
 3987get_goal_vars(G,LHead,LVF,G) :-
 3988        % term_variables(G,LV0),
 3989        vars_in_term([G],[],LVI),
 3990        aleph_ord_subtract(LVI,LHead,LVF).
 3991
 3992calculate_independent_sets([],BSets,BSets).
 3993calculate_independent_sets([G|Ls],BSets0,BSetsF) :-
 3994        add_goal_to_set(G,BSets0,BSetsI),
 3995        calculate_independent_sets(Ls,BSetsI,BSetsF).
 3996
 3997add_goal_to_set(g(I,LV,G),Sets0,SetsF) :-
 3998        add_to_sets(Sets0,LV,[g(I,LV,G)],SetsF).
 3999
 4000add_to_sets([],LV,Gs,[[LV|Gs]]).
 4001add_to_sets([[LV|Gs]|Sets0],LVC,GsC,[[LV|Gs]|SetsF]) :-
 4002        aleph_ord_disjoint(LV,LVC), !,
 4003        add_to_sets(Sets0,LVC,GsC,SetsF).
 4004add_to_sets([[LV|Gs]|Sets0],LVC,GsC,SetsF) :-
 4005        aleph_ord_union(LV,LVC,LVN),
 4006        join_goals(Gs,GsC,GsN),
 4007        add_to_sets(Sets0,LVN,GsN,SetsF).
 4008
 4009join_goals([],L,L):- !.
 4010join_goals(L,[],L):- !.
 4011join_goals([g(I1,VL1,G1)|T],[g(I2,VL2,G2)|T2],Z) :-
 4012        I1 < I2, !,
 4013        Z = [g(I1,VL1,G1)|TN],
 4014        join_goals(T,[g(I2,VL2,G2)|T2],TN).
 4015join_goals([H|T],[g(I2,VL2,G2)|T2],Z) :-
 4016        Z = [g(I2,VL2,G2)|TN],
 4017        join_goals(T,[H|T2],TN).
 4018
 4019compile_clause(Goals,Head,(Head:-Body)):-
 4020        compile_clause2(Goals,Body).
 4021
 4022compile_clause2([[_|B]], B1):-
 4023	!,
 4024        glist_to_goals(B,B1).
 4025compile_clause2([[_|B]|Bs],(B1,!,NB)):-
 4026        glist_to_goals(B,B1),
 4027        compile_clause2(Bs,NB).
 4028
 4029glist_to_goals([g(_,_,Goal)],Goal):- !.
 4030glist_to_goals([g(_,_,Goal)|Goals],(Goal,Goals1)):-
 4031        glist_to_goals(Goals,Goals1).
 4032
 4033% remove literals subsumed in the body of a clause
 4034remove_subsumed([Head|Lits],Lits1):-
 4035	delete(Lit,Lits,Left),
 4036	\+(\+(redundant(Lit,[Head|Lits],[Head|Left]))), !,
 4037	remove_subsumed([Head|Left],Lits1).
 4038remove_subsumed(L,L).
 4039
 4040% determine if Lit is subsumed by a body literal
 4041redundant(Lit,Lits,[Head|Body]):-
 4042	copy_term([Head|Body],Rest1),
 4043	member(Lit1,Body),
 4044	Lit = Lit1,
 4045	aleph_subsumes(Lits,Rest1).
 aleph_subsumes(+Lits:list, +Lits1:list) is det
determine if Lits subsumes Lits1 /
 4052aleph_subsumes(Lits,Lits1):-
 4053	\+(\+((numbervars(Lits,0,_),numbervars(Lits1,0,_),aleph_subset1(Lits,Lits1)))).
 4054
 4055
 4056%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 4057% S A T  /  R E D U C E
 sat(:Num:int) is det
Num is an integer. Builds the bottom clause for positive example number Num. Positive examples are numbered from 1, and the numbering corresponds to the order of appearance. /
 4067sat(M:Num):-
 4068	sat(Num,M).
 4069
 4070sat(Num,M):-
 4071	integer(Num),!,
 4072	M:example(Num,pos,_),
 4073	sat(pos,Num,M),!.
 4074sat(Example,M):-
 4075	record_example(check,uspec,Example,Num,M),
 4076	sat(uspec,Num,M), !.
 4077
 4078sat(Type,Num,M):-
 4079        setting(construct_bottom,false,M), !,
 4080        sat_prelims(M),
 4081	M:example(Num,Type,Example),
 4082	broadcast(start(sat(Num))),
 4083	p1_message('sat'), p_message(Num), p_message(Example),
 4084	record_sat_example(Num,M),
 4085	asserta(M:'$aleph_sat'(example,example(Num,Type))),
 4086	asserta(M:'$aleph_sat'(hovars,[])),
 4087	broadcast(end(sat(Num, 0, 0.0))).
 4088sat(Type,Num,M):-
 4089	setting(construct_bottom,reduction,M), !,
 4090	sat_prelims(M),
 4091	M:example(Num,Type,Example),
 4092	broadcast(start(sat(Num))),
 4093	p1_message('sat'), p_message(Num), p_message(Example),
 4094	record_sat_example(Num,M),
 4095	asserta(M:'$aleph_sat'(example,example(Num,Type))),
 4096	integrate_head_lit(HeadOVars,M),
 4097	asserta(M:'$aleph_sat'(hovars,HeadOVars)),
 4098	broadcast(end(sat(Num, 0, 0.0))).
 4099sat(Type,Num,M):-
 4100	set(stage,saturation,M),
 4101	sat_prelims(M),
 4102	M:example(Num,Type,Example),
 4103	broadcast(start(sat(Num))),
 4104	p1_message('sat'), p_message(Num), p_message(Example),
 4105	record_sat_example(Num,M),
 4106	asserta(M:'$aleph_sat'(example,example(Num,Type))),
 4107	split_args(Example,Mode,Input,Output,Constants,M),
 4108	integrate_args(unknown,Example,Output,M),
 4109	stopwatch(StartClock),
 4110	assertz(M:'$aleph_sat_atom'(Example,mode(Mode,Output,Input,Constants))),
 4111	M:'$aleph_global'(i,set(i,Ival)),
 4112	flatten(0,Ival,0,Last1,M),
 4113	M:'$aleph_sat_litinfo'(1,_,Atom,_,_,_),
 4114	get_vars(Atom,Output,HeadOVars),
 4115	asserta(M:'$aleph_sat'(hovars,HeadOVars)),
 4116	get_vars(Atom,Input,HeadIVars),
 4117	asserta(M:'$aleph_sat'(hivars,HeadIVars)),
 4118	functor(Example,Name,Arity), 
 4119	get_determs(Name/Arity,L,M),
 4120	(M:'$aleph_global'(determination,determination(Name/Arity,'='/2))->
 4121		asserta(M:'$aleph_sat'(eq,true));
 4122		asserta(M:'$aleph_sat'(eq,false))),
 4123	get_atoms(L,1,Ival,Last1,Last,M),
 4124	stopwatch(StopClock),
 4125	Time is StopClock - StartClock,
 4126	asserta(M:'$aleph_sat'(lastlit,Last)),
 4127	asserta(M:'$aleph_sat'(botsize,Last)),
 4128	update_generators(M),
 4129	rm_moderepeats(Last,Repeats,M),
 4130	rm_commutative(Last,Commutative,M),
 4131	rm_symmetric(Last,Symmetric,M),
 4132	rm_redundant(Last,Redundant,M),
 4133	rm_uselesslits(Last,NotConnected,M),
 4134	rm_nreduce(Last,NegReduced,M),
 4135	/* write("Last:"),nl,write(Last),nl,
 4136	write("Repeats:"),nl,write(Repeats),nl,
 4137	write("NotConnected:"),nl,write(NotConnected),nl,
 4138	write("Commutative:"),nl,write(Commutative),nl,
 4139	write("Symmetric:"),nl,write(Symmetric),nl,
 4140	write("Redundant:"),nl,write(Redundant),nl,
 4141	write("NegReduced:"),nl,write(NegReduced),nl, */
 4142	TotalLiterals is
 4143		Last-Repeats-NotConnected-Commutative-Symmetric-Redundant-NegReduced,
 4144	show(bottom,M),
 4145	p1_message('literals'), p_message(TotalLiterals),
 4146	p1_message('saturation time'), p_message(Time),
 4147	broadcast(end(sat(Num, TotalLiterals, Time))),
 4148	store(bottom,M),
 4149	noset(stage,M).
 4150sat(_,_,M):-
 4151	noset(stage,M).
 reduce(:Clause:term) is det
Run a search on the current bottom clause, which can be obtained with the sat/1 command. /
 4158reduce(M:Cl):-
 4159	setting(search,Search,M), 
 4160	catch(reduce(Search,Cl,M),abort,reinstate_values), !.
 4161
 4162reduce(Search,M):-
 4163	reduce(Search,_Cl,M).
 4164% no search: add bottom clause as hypothesis
 4165reduce(false,B,M):-
 4166	!,
 4167	add_bottom(B,M).
 4168% iterative beam search as described by Ross Quinlan+MikeCameron-Jones,IJCAI-95
 4169reduce(ibs,RClause,M):-
 4170	!,
 4171	retractall(M:'$aleph_search'(ibs_rval,_)),
 4172	retractall(M:'$aleph_search'(ibs_nodes,_)),
 4173	retractall(M:'$aleph_search'(ibs_selected,_)),
 4174	store_values([openlist,caching,explore],M),
 4175	set(openlist,1,M),
 4176	set(caching,true,M),
 4177	set(explore,true,M),
 4178	asserta(M:'$aleph_search'(ibs_rval,1.0)),
 4179	asserta(M:'$aleph_search'(ibs_nodes,0)),
 4180	setting(evalfn,Evalfn,M),
 4181	get_start_label(Evalfn,Label,M),
 4182	(M:'$aleph_sat'(example,example(Num,Type)) ->
 4183		M:example(Num,Type,Example),
 4184		asserta(M:'$aleph_search'(ibs_selected,selected(Label,(Example:-true),
 4185				[Num-Num],[])));
 4186		asserta(M:'$aleph_search'(ibs_selected,selected(Label,(false:-true),
 4187				[],[])))),
 4188	stopwatch(Start),
 4189	repeat,
 4190	setting(openlist,OldOpen,M),
 4191	p1_message('ibs beam width'), p_message(OldOpen),
 4192	find_clause(bf,M),
 4193	M:'$aleph_search'(current,current(_,Nodes0,[PC,NC|_]/_)),
 4194	N is NC + PC,
 4195	estimate_error_rate(Nodes0,0.5,N,NC,NewR),
 4196	p1_message('ibs estimated error'), p_message(NewR),
 4197	retract(M:'$aleph_search'(ibs_rval,OldR)),
 4198	retract(M:'$aleph_search'(ibs_nodes,Nodes1)),
 4199        M:'$aleph_search'(selected,selected(BL,RCl,PCov,NCov)),
 4200	NewOpen is 2*OldOpen,
 4201	Nodes2 is Nodes0 + Nodes1,
 4202	set(openlist,NewOpen,M),
 4203	asserta(M:'$aleph_search'(ibs_rval,NewR)),
 4204	asserta(M:'$aleph_search'(ibs_nodes,Nodes2)),
 4205	((NewR >= OldR; NewOpen > 512) -> true;
 4206		retract(M:'$aleph_search'(ibs_selected,selected(_,_,_,_))),
 4207		asserta(M:'$aleph_search'(ibs_selected,selected(BL,RCl,PCov,NCov))),
 4208		fail),
 4209	!,
 4210	stopwatch(Stop),
 4211	Time is Stop - Start,
 4212	retractall(M:'$aleph_search'(ibs_rval,_)),
 4213	retract(M:'$aleph_search'(ibs_nodes,Nodes)),
 4214        retract(M:'$aleph_search'(ibs_selected,selected(BestLabel,RClause,PCover,NCover))),
 4215	add_hyp(BestLabel,RClause,PCover,NCover,M),
 4216	p1_message('ibs clauses constructed'), p_message(Nodes),
 4217	p1_message('ibs search time'), p_message(Time),
 4218	p_message('ibs best clause'),
 4219	pp_dclause(RClause,M),
 4220	show_stats(Evalfn,BestLabel),
 4221	record_search_stats(RClause,Nodes,Time),
 4222	reinstate_values([openlist,caching,explore]).
 4223
 4224% iterative deepening search
 4225reduce(id,RClause,M):-
 4226	!,
 4227	retractall(M:'$aleph_search'(id_nodes,_)),
 4228	retractall(M:'$aleph_search'(id_selected,_)),
 4229	store_values([caching,clauselength],M),
 4230	setting(clauselength,MaxCLen,M),
 4231	set(clauselength,1,M),
 4232	set(caching,true,M),
 4233	asserta(M:'$aleph_search'(id_nodes,0)),
 4234	setting(evalfn,Evalfn,M),
 4235	get_start_label(Evalfn,Label,M),
 4236	(M:'$aleph_sat'(example,example(Num,Type)) ->
 4237		M:example(Num,Type,Example),
 4238		asserta(M:'$aleph_search'(id_selected,selected(Label,(Example:-true),
 4239				[Num-Num],[])));
 4240		asserta(M:'$aleph_search'(id_selected,selected(Label,(false:-true),
 4241				[],[])))),
 4242	stopwatch(Start),
 4243	repeat,
 4244	setting(clauselength,OldCLen,M),
 4245	p1_message('id clauselength setting'), p_message(OldCLen),
 4246	find_clause(df,M),
 4247	M:'$aleph_search'(current,current(_,Nodes0,_)),
 4248	retract(M:'$aleph_search'(id_nodes,Nodes1)),
 4249        M:'$aleph_search'(selected,selected([P,N,L,F|T],RCl,PCov,NCov)),
 4250	M:'$aleph_search'(id_selected,selected([_,_,_,F1|_],_,_,_)),
 4251	NewCLen is OldCLen + 1,
 4252	Nodes2 is Nodes0 + Nodes1,
 4253	set(clauselength,NewCLen,M),
 4254	M:'$aleph_search'(id_nodes,Nodes2),
 4255	(F1 >= F -> true;
 4256		retract(M:'$aleph_search'(id_selected,selected([_,_,_,F1|_],_,_,_))),
 4257		asserta(M:'$aleph_search'(id_selected,selected([P,N,L,F|T],RCl,PCov,NCov))),
 4258		set(best,[P,N,L,F|T],M)),
 4259	NewCLen > MaxCLen,
 4260	!,
 4261	stopwatch(Stop),
 4262	Time is Stop - Start,
 4263	retract(M:'$aleph_search'(id_nodes,Nodes)),
 4264        retract(M:'$aleph_search'(id_selected,selected(BestLabel,RClause,PCover,NCover))),
 4265	add_hyp(BestLabel,RClause,PCover,NCover,M),
 4266	p1_message('id clauses constructed'), p_message(Nodes),
 4267	p1_message('id search time'), p_message(Time),
 4268	p_message('id best clause'),
 4269	pp_dclause(RClause,M),
 4270	show_stats(Evalfn,BestLabel),
 4271	record_search_stats(RClause,Nodes,Time,M),
 4272	noset(best,M),
 4273	reinstate_values([caching,clauselength],M).
 4274
 4275% iterative language search as described by Rui Camacho, 1996
 4276reduce(ils,RClause,M):-
 4277	!,
 4278	retractall(M:'$aleph_search'(ils_nodes,_)),
 4279	retractall(M:'$aleph_search'(ils_selected,_)), 
 4280	store_values([caching,language],M),
 4281	set(searchstrat,bf,M),
 4282	set(language,1,M),
 4283	set(caching,true,M),
 4284	asserta(M:'$aleph_search'(ils_nodes,0)),
 4285	setting(evalfn,Evalfn,M),
 4286	get_start_label(Evalfn,Label,M),
 4287	(M:'$aleph_sat'(example,example(Num,Type)) ->
 4288		M:example(Num,Type,Example),
 4289		asserta(M:'$aleph_search'(ils_selected,selected(Label,(Example:-true),
 4290				[Num-Num],[])));
 4291		asserta(M:'$aleph_search'(ils_selected,selected(Label,(false:-true),
 4292				[],[])))),
 4293	stopwatch(Start),
 4294	repeat,
 4295	setting(language,OldLang,M),
 4296	p1_message('ils language setting'), p_message(OldLang),
 4297	find_clause(bf,M),
 4298	M:'$aleph_search'(current,current(_,Nodes0,_)),
 4299	retract(M:'$aleph_search'(ils_nodes,Nodes1)),
 4300        M:'$aleph_search'(selected,selected([P,N,L,F|T],RCl,PCov,NCov)),
 4301	M:'$aleph_search'(ils_selected,selected([_,_,_,F1|_],_,_,_)),
 4302	NewLang is OldLang + 1,
 4303	Nodes2 is Nodes0 + Nodes1,
 4304	set(language,NewLang,M),
 4305	asserta(M:'$aleph_search'(ils_nodes,Nodes2)),
 4306	(F1 >= F -> true;
 4307		retract(M:'$aleph_search'(ils_selected,selected([_,_,_,F1|_],_,_,_))),
 4308		asserta(M:'$aleph_search'(ils_selected,selected([P,N,L,F|T],RCl,PCov,NCov))),
 4309		set(best,[P,N,L,F|T],M),
 4310		fail),
 4311	!,
 4312	stopwatch(Stop),
 4313	Time is Stop - Start,
 4314	retract(M:'$aleph_search'(ils_nodes,Nodes)),
 4315        retract(M:'$aleph_search'(ils_selected,selected(BestLabel,RClause,PCover,NCover))),
 4316	add_hyp(BestLabel,RClause,PCover,NCover,M),
 4317	p1_message('ils clauses constructed'), p_message(Nodes),
 4318	p1_message('ils search time'), p_message(Time),
 4319	p_message('ils best clause'),
 4320	pp_dclause(RClause,M),
 4321	show_stats(Evalfn,BestLabel),
 4322	record_search_stats(RClause,Nodes,Time,M),
 4323	noset(best,M),
 4324	reinstate_values([caching,language],M).
 4325
 4326
 4327% implementation of a randomised local search for clauses
 4328% currently, this can use either: simulated annealing with a fixed temp
 4329% or a GSAT-like algorithm
 4330% the choice of these is specified by the parameter: rls_type
 4331% both annealing and GSAT employ random multiple restarts
 4332% and a limit on the number of moves
 4333%	the number of restarts is specified by set(tries,...)
 4334%	the number of moves is specified by set(moves,...)
 4335% annealing currently restricted to using a fixed temperature
 4336%	the temperature is specified by set(temperature,...)
 4337%	the use of a fixed temp. makes it equivalent to the Metropolis alg.
 4338% GSAT if given a ``random-walk probability'' performs Selman et als walksat
 4339%	the walk probability is specified by set(walk,...)
 4340%	a walk probability of 0 is equivalent to doing standard GSAT
 4341reduce(rls,RBest,M):-
 4342	!,
 4343	setting(tries,MaxTries,M),
 4344	MaxTries >= 1,
 4345	store_values([caching,refine,refineop],M),
 4346	set(searchstrat,heuristic,M),
 4347	set(caching,true,M),
 4348	setting(refine,Refine,M),
 4349	(Refine \= false  -> true; set(refineop,rls,M)),
 4350	setting(threads,Threads,M),
 4351	rls_search(Threads, MaxTries, Time, Nodes, selected(BestLabel,
 4352					RBest,PCover,NCover),M),
 4353	add_hyp(BestLabel,RBest,PCover,NCover,M),
 4354	p1_message('rls nodes constructed'), p_message(Nodes),
 4355	p1_message('rls search time'), p_message(Time),
 4356	p_message('rls best result'),
 4357	pp_dclause(RBest,M),
 4358	setting(evalfn,Evalfn,M),
 4359	show_stats(Evalfn,BestLabel),
 4360	record_search_stats(RBest,Nodes,Time,M),
 4361	noset(best,M),
 4362	reinstate_values([caching,refine,refineop],M).
 4363
 4364
 4365% stochastic clause selection based on ordinal optimisation
 4366% see papers by Y.C. Ho and colleagues for more details
 4367reduce(scs,RBest,M):-
 4368	!,
 4369	store_values([tries,moves,rls_type,clauselength_distribution],M),
 4370	stopwatch(Start),
 4371	(setting(scs_sample,SampleSize,M) -> true;
 4372		setting(scs_percentile,K,M),
 4373		K > 0.0,
 4374		setting(scs_prob,P,M),
 4375		P < 1.0,
 4376		SampleSize is integer(log(1-P)/log(1-K/100) + 1)),
 4377	(setting(scs_type,informed,M,M)->
 4378		(setting(clauselength_distribution,_D,M,M) -> true;
 4379			setting(clauselength,CL,M),
 4380			estimate_clauselength_distribution(CL,100,K,D,M),
 4381			% max_in_list(D,Prob-Length),
 4382			% p1_message('using clauselength distribution'),
 4383			% p_message([Prob-Length]),
 4384			% set(clauselength_distribution,[Prob-Length]));
 4385			p1_message('using clauselength distribution'),
 4386			p_message(D),
 4387			set(clauselength_distribution,D,M));
 4388		true),
 4389	set(tries,SampleSize,M),
 4390	set(moves,0,M),
 4391	set(rls_type,gsat,M),
 4392	reduce(rls,M),
 4393	stopwatch(Stop),
 4394	Time is Stop - Start,
 4395	M:'$aleph_search'(rls_nodes,Nodes),
 4396        M:'$aleph_search'(rls_selected,selected(BestLabel,RBest,_,_)),
 4397	p1_message('scs nodes constructed'), p_message(Nodes),
 4398	p1_message('scs search time'), p_message(Time),
 4399	p_message('scs best result'),
 4400	pp_dclause(RBest,M),
 4401	setting(evalfn,Evalfn,M),
 4402	show_stats(Evalfn,BestLabel),
 4403	record_search_stats(RBest,Nodes,Time,M),
 4404	p1_message('scs search time'), p_message(Time),
 4405	reinstate_values([tries,moves,rls_type,clauselength_distribution],M).
 4406
 4407% simple association rule search
 4408% For a much more sophisticated approach see: L. Dehaspe, PhD Thesis, 1998
 4409% Here, simply find all rules within search that cover at least
 4410% a pre-specificed fraction of the positive examples
 4411reduce(ar,Cl,M):-
 4412	!,
 4413	clear_cache(M),
 4414	(setting(pos_fraction,PFrac,M) -> true;
 4415		p_message('value required for pos_fraction parameter'),
 4416		fail),
 4417        M:'$aleph_global'(atoms_left,atoms_left(pos,Pos)),
 4418	retract(M:'$aleph_global'(atoms_left,atoms_left(neg,Neg))),
 4419	interval_count(Pos,P),
 4420	MinPos is PFrac*P,
 4421	store_values([minpos,evalfn,explore,caching,minacc,good],M),
 4422	set(searchstrat,bf,M),
 4423	set(minpos,MinPos,M),
 4424	set(evalfn,coverage,M),
 4425	set(explore,true,M),
 4426	set(caching,true,M),
 4427	set(minacc,0.0,M),
 4428	set(good,true,M),
 4429	asserta(M:'$aleph_global'(atoms_left,atoms_left(neg,[]))),
 4430	find_clause(bf,M),
 4431	show(good,M),
 4432	good_clauses(Cl,M),
 4433	retract(M:'$aleph_global'(atoms_left,atoms_left(neg,[]))),
 4434	asserta(M:'$aleph_global'(atoms_left,atoms_left(neg,Neg))),
 4435	reinstate_values([minpos,evalfn,explore,caching,minacc,good],M).
 4436
 4437% search for integrity constraints
 4438% modelled on the work by L. De Raedt and L. Dehaspe, 1996
 4439reduce(ic,Cl,M):-
 4440	!,
 4441	store_values([minpos,minscore,evalfn,explore,refineop],M),
 4442	setting(refineop,RefineOp,M),
 4443	(RefineOp = false -> set(refineop,auto,M); true),
 4444	set(minpos,0,M),
 4445	set(searchstrat,bf,M),
 4446	set(evalfn,coverage,M),
 4447	set(explore,true,M),
 4448	setting(noise,N,M),
 4449	MinScore is -N,
 4450	set(minscore,MinScore,M),
 4451	find_clause(bf,Cl,M),
 4452	reinstate_values([minpos,minscore,evalfn,explore,refineop],M).
 4453
 4454reduce(bf,Cl,M):-
 4455	!,
 4456	find_clause(bf,Cl,M).
 4457
 4458reduce(df,Cl,M):-
 4459	!,
 4460	find_clause(df,Cl,M).
 4461
 4462reduce(heuristic,Cl,M):-
 4463	!,
 4464	find_clause(heuristic,Cl,M).
 4465
 4466
 4467% find_clause(Search,M) where Search is one of bf, df, heuristic
 4468find_clause(Search,M):-
 4469	find_clause(Search,_Cl,M).
 4470
 4471find_clause(Search,RClause,M):-
 4472	set(stage,reduction,M),
 4473	set(searchstrat,Search,M),
 4474	p_message('reduce'),
 4475	reduce_prelims(L,P,N,M),
 4476	asserta(M:'$aleph_search'(openlist,[])),
 4477	get_search_settings(S,M),
 4478	arg(4,S,_/Evalfn),
 4479	get_start_label(Evalfn,Label,M),
 4480	(M:'$aleph_sat'(example,example(Num,Type)) ->
 4481		M:example(Num,Type,Example),
 4482		asserta(M:'$aleph_search'(selected,selected(Label,(Example:-true),
 4483							[Num-Num],[])));
 4484		asserta(M:'$aleph_search'(selected,selected(Label,(false:-true),[],[])))),
 4485	arg(13,S,MinPos),
 4486	interval_count(P,PosLeft),
 4487	PosLeft >= MinPos,
 4488	M:'$aleph_search'(selected,selected(L0,C0,P0,N0)),
 4489	add_hyp(L0,C0,P0,N0,M),
 4490        (M:'$aleph_global'(max_set,max_set(Type,Num,Label1,ClauseNum))->
 4491		BestSoFar = Label1/ClauseNum;
 4492		(M:'$aleph_global'(best,set(best,Label2))->
 4493			BestSoFar = Label2/0;
 4494			BestSoFar = Label/0)),
 4495        asserta(M:'$aleph_search'(best_label,BestSoFar)),
 4496	p1_message('best label so far'), p_message(BestSoFar),
 4497        arg(3,S,RefineOp),
 4498		
 4499	stopwatch(StartClock),
 4500        (RefineOp = false ->
 4501                get_gains(S,0,BestSoFar,[],false,[],0,L,[1],P,N,[],1,Last,NextBest,M),
 4502		update_max_head_count(0,Last,M);
 4503		clear_cache(M),
 4504		
 4505		interval_count(P,MaxPC),
 4506		asserta(M:'$aleph_local'(max_head_count,MaxPC)),
 4507		StartClause = 0-[Num,Type,[],aleph_false],
 4508                get_gains(S,0,BestSoFar,StartClause,_,_,_,L,[StartClause],
 4509				P,N,[],1,Last,NextBest,M)),
 4510        asserta(M:'$aleph_search_expansion'(1,0,1,Last)),
 4511		
 4512	get_nextbest(S,_,M),
 4513	asserta(M:'$aleph_search'(current,current(1,Last,NextBest))),
 4514	
 4515	search(S,Nodes,M),
 4516	stopwatch(StopClock),
 4517	Time is StopClock - StartClock,
 4518        M:'$aleph_search'(selected,selected(BestLabel,RClause,PCover,NCover)),
 4519	retract(M:'$aleph_search'(openlist,_)),
 4520	add_hyp(BestLabel,RClause,PCover,NCover,M),
 4521	p1_message('clauses constructed'), p_message(Nodes),
 4522	p1_message('search time'), p_message(Time),
 4523	p_message('best clause'),
 4524	pp_dclause(RClause,M),
 4525	show_stats(Evalfn,BestLabel),
 4526	update_search_stats(Nodes,Time,M),
 4527	record_search_stats(RClause,Nodes,Time,M),
 4528	noset(stage,M),
 4529	!.
 4530find_clause(_,RClause,M):-
 4531        M:'$aleph_search'(selected,selected(BestLabel,RClause,PCover,NCover)),
 4532	retract(M:'$aleph_search'(openlist,_)),
 4533	add_hyp(BestLabel,RClause,PCover,NCover,M),
 4534	p_message('best clause'),
 4535	pp_dclause(RClause,M),
 4536	(setting(evalfn,Evalfn,M) -> true; Evalfn = coverage),
 4537	show_stats(Evalfn,BestLabel),
 4538	noset(stage,M),
 4539	!.
 4540
 4541% find_theory(Search,M) where Search is rls only at present
 4542find_theory(rls,Program,M):-
 4543	!,
 4544	retractall(M:'$aleph_search'(rls_move,_)),
 4545	retractall(M:'$aleph_search'(rls_nodes,_)),
 4546	retractall(M:'$aleph_search'(rls_parentstats,_)),
 4547	retractall(M:'$aleph_search'(rls_selected,_)),
 4548	setting(tries,MaxTries,M),
 4549	MaxTries >= 1,
 4550	store_values([caching,store_bottom],M),
 4551	set(caching,false,M),
 4552	set(store_bottom,true,M),
 4553        M:'$aleph_global'(atoms,atoms(pos,PosSet)),
 4554        M:'$aleph_global'(atoms,atoms(neg,NegSet)),
 4555        interval_count(PosSet,P0),
 4556        interval_count(NegSet,N0),
 4557	setting(evalfn,Evalfn,M),
 4558        complete_label(Evalfn,[0-[0,0,[],false]],[P0,N0,1],Label,M),
 4559	asserta(M:'$aleph_search'(rls_selected,selected(Label,[0-[0,0,[],false]],
 4560						PosSet,NegSet))),
 4561	asserta(M:'$aleph_search'(rls_nodes,0)),
 4562	asserta(M:'$aleph_search'(rls_restart,1)),
 4563	get_search_settings(S,M),
 4564	set(best,Label,M),
 4565	stopwatch(Start),
 4566	repeat,
 4567	retractall(M:'$aleph_search'(rls_parentstats,_)),
 4568	retractall(M:'$aleph_search'(rls_move,_)),
 4569	retractall(M:'$aleph_search_seen'(_,_)),
 4570	asserta(M:'$aleph_search'(rls_move,1)),
 4571	asserta(M:'$aleph_search'(rls_parentstats,stats(Label,PosSet,NegSet))),
 4572	M:'$aleph_search'(rls_restart,R),
 4573	p1_message('restart'), p_message(R),
 4574	find_theory1(rls,M),
 4575	M:'$aleph_search'(current,current(_,Nodes0,_)),
 4576	retract(M:'$aleph_search'(rls_nodes,Nodes1)),
 4577        M:'$aleph_search'(selected,selected([P,N,L,F|T],RCl,PCov,NCov)),
 4578	M:'$aleph_search'(rls_selected,selected([_,_,_,F1|_],_,_,_)),
 4579	retract(M:'$aleph_search'(rls_restart,R)),
 4580	R1 is R + 1,
 4581	asserta(M:'$aleph_search'(rls_restart,R1)),
 4582	Nodes2 is Nodes0 + Nodes1,
 4583	asserta(M:'$aleph_search'(rls_nodes,Nodes2)),
 4584	(F1 >= F -> true;
 4585		retract(M:'$aleph_search'(rls_selected,selected([_,_,_,F1|_],_,_,_))),
 4586		asserta(M:'$aleph_search'(rls_selected,selected([P,N,L,F|T],RCl,PCov,NCov))),
 4587		set(best,[P,N,L,F|T],M)),
 4588	setting(best,BestSoFar,M),
 4589	(R1 > MaxTries;discontinue_search(S,BestSoFar/_,Nodes2,M)),
 4590	!,
 4591	stopwatch(Stop),
 4592	Time is Stop - Start,
 4593	M:'$aleph_search'(rls_nodes,Nodes),
 4594        M:'$aleph_search'(rls_selected,selected(BestLabel,RBest,PCover,NCover)),
 4595	add_hyp(BestLabel,RBest,PCover,NCover,M),
 4596	p1_message('nodes constructed'), p_message(Nodes),
 4597	p1_message('search time'), p_message(Time),
 4598	p_message('best theory'),
 4599	Program=RBest,
 4600	pp_dclauses(RBest,M),
 4601	show_stats(Evalfn,BestLabel),
 4602	record_search_stats(RBest,Nodes,Time,M),
 4603	noset(best,M),
 4604	reinstate_values([caching,refine,refineop,store_bottom],M).
 4605
 4606find_theory1(_,M):-
 4607	clean_up_reduce(M),
 4608        M:'$aleph_global'(atoms,atoms(pos,Pos)),
 4609        M:'$aleph_global'(atoms,atoms(neg,Neg)),
 4610        asserta(M:'$aleph_search'(openlist,[])),
 4611	asserta(M:'$aleph_search'(nextnode,none)),
 4612        stopwatch(StartClock),
 4613        get_search_settings(S,M),
 4614	arg(4,S,_/Evalfn),
 4615        interval_count(Pos,P),
 4616        interval_count(Neg,N),
 4617        complete_label(Evalfn,[0-[0,0,[],false]],[P,N,1],Label,M),
 4618	asserta(M:'$aleph_search'(selected,selected(Label,[0-[0,0,[],false]],Pos,Neg))),
 4619	get_theory_gain(S,0,Label/0,[0-[0,0,[],false]],Pos,Neg,P,N,NextBest,Last,M),
 4620	asserta(M:'$aleph_search'(current,current(0,Last,NextBest))),
 4621	get_nextbest(S,_,M),
 4622	tsearch(S,Nodes,M),
 4623	stopwatch(StopClock),
 4624	Time is StopClock - StartClock,
 4625	M:'$aleph_search'(selected,selected(BestLabel,RTheory,PCover,NCover)),
 4626	retract(M:'$aleph_search'(openlist,_)),
 4627	add_hyp(BestLabel,RTheory,PCover,NCover,M),
 4628	p1_message('theories constructed'), p_message(Nodes),
 4629	p1_message('search time'), p_message(Time),
 4630	p_message('best theory'),
 4631	pp_dclauses(RTheory,M),
 4632	show_stats(Evalfn,BestLabel),
 4633	update_search_stats(Nodes,Time,M),
 4634	record_tsearch_stats(RTheory,Nodes,Time,M).
 4635
 4636estimate_error_rate(H,Del,N,E,R):-
 4637	TargetProb is 1-exp(log(1-Del)/H),
 4638	estimate_error(1.0/0.0,0.0/1.0,TargetProb,N,E,R).
 4639
 4640estimate_error(L/P1,U/P2,P,N,E,R):-
 4641	M is (L+U)/2,
 4642	binom_lte(N,M,E,P3),
 4643	ADiff is abs(P - P3),
 4644	(ADiff < 0.00001 ->
 4645		R is M;
 4646		(P3 > P ->
 4647			estimate_error(L/P1,M/P3,P,N,E,R);
 4648			estimate_error(M/P3,U/P2,P,N,E,R)
 4649		)
 4650	).
 4651		
 4652
 4653zap_rest(Lits,M):-
 4654	retract(M:'$aleph_sat_litinfo'(LitNum,Depth,Atom,I,O,D)),
 4655	(aleph_member1(LitNum,Lits) ->
 4656		intersect1(Lits,D,D1,_),
 4657		asserta(M:'$aleph_sat_litinfo'(LitNum,Depth,Atom,I,O,D1));
 4658		true),
 4659	fail.
 4660zap_rest(_,_M).
 4661
 4662sat_prelims(M):-
 4663	clean_up_sat(M),
 4664	clean_up_hypothesis(M),
 4665	reset_counts(M),
 4666	set_up_builtins(M).
 4667	
 4668
 4669reduce_prelims(L,P,N,M):-
 4670	clean_up_reduce(M),
 4671	check_posonly(M),
 4672	check_auto_refine(M),
 4673	(M:'$aleph_sat'(lastlit,L) -> true;
 4674		L = 0, asserta(M:'$aleph_sat'(lastlit,L))),
 4675	(M:'$aleph_sat'(botsize,_B) -> true;
 4676		B = 0, asserta(M:'$aleph_sat'(botsize,B))),
 4677        ((M:'$aleph_global'(lazy_evaluate,lazy_evaluate(_));setting(greedy,true,M))->
 4678                M:'$aleph_global'(atoms_left,atoms_left(pos,P));
 4679                M:'$aleph_global'(atoms,atoms(pos,P))),
 4680	setting(evalfn,E,M),
 4681	(E = posonly -> NType = rand; NType = neg),
 4682	M:'$aleph_global'(atoms_left,atoms_left(NType,N)),
 4683	asserta(M:'$aleph_search'(nextnode,none)).
 4684
 4685set_up_builtins(M):-
 4686	gen_nlitnum(Cut,M),
 4687	asserta(M:'$aleph_sat_litinfo'(Cut,0,'!',[],[],[])).
 4688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 4689% T H R E A D S
 4690
 4691% multi-threaded randomised local search
 4692rls_search(1, MaxTries, Time, Nodes, Selected,M) :-
 4693 	!,
 4694	retractall(M:'$aleph_search'(rls_restart,_)),
 4695	retractall(M:'$aleph_search'(rls_nodes,_)),
 4696	retractall(M:'$aleph_search'(rls_selected,_)),
 4697	asserta(M:'$aleph_search'(rls_restart,1)),
 4698	setting(evalfn,Evalfn,M),
 4699	get_start_label(Evalfn,Label,M),
 4700	set(best,Label,M),
 4701	get_search_settings(S,M),
 4702	arg(4,S,SearchStrat/_),
 4703	(M:'$aleph_sat'(example,example(Num,Type)) ->
 4704		M:example(Num,Type,Example),
 4705		asserta(M:'$aleph_search'(rls_selected,selected(Label,
 4706						(Example:-true),[Num-Num],[])));
 4707		asserta(M:'$aleph_search'(rls_selected,selected(Label,
 4708						(false:-true),[],[])))
 4709	),
 4710 	asserta(M:'$aleph_search'(rls_nodes,0)),
 4711 	stopwatch(Start),
 4712	estimate_numbers(_,M),
 4713 	repeat,
 4714 	retract(M:'$aleph_search'(rls_restart,R)),
 4715 	R1 is R + 1,
 4716 	asserta(M:'$aleph_search'(rls_restart,R1)),
 4717	rls_thread(R, SearchStrat, Label, Nodes0, selected(Best,RCl,PCov,NCov),M),
 4718 	Best = [_,_,_,F|_],
 4719 	M:'$aleph_search'(rls_selected,selected([_,_,_,F1|_],_,_,_)),
 4720 	(F1 >= F -> true;
 4721 		retract(M:'$aleph_search'(rls_selected,selected([_,_,_,F1|_],
 4722							_,_,_))),
 4723 		asserta(M:'$aleph_search'(rls_selected,selected(Best,RCl,
 4724							PCov,NCov))),
 4725 		set(best,Best,M)
 4726 	),
 4727 	setting(best,BestSoFar,M),
 4728 	retract(M:'$aleph_search'(rls_nodes,Nodes1)),
 4729 	Nodes2 is Nodes0 + Nodes1,
 4730 	asserta(M:'$aleph_search'(rls_nodes,Nodes2)),
 4731	(R1 > MaxTries; discontinue_search(S,BestSoFar/_,Nodes2,M)),
 4732 	!,
 4733 	stopwatch(Stop),
 4734 	Time is Stop - Start,
 4735 	retractall(M:'$aleph_search'(rls_restart,_)),
 4736	retract(M:'$aleph_search'(rls_nodes,Nodes)),
 4737        retract(M:'$aleph_search'(rls_selected,Selected)).
 4738rls_search(N, MaxTries, Time, Nodes, Selected,M) :-
 4739	retractall(M:'$aleph_search'(rls_restart,_)),
 4740	retractall(M:'$aleph_search'(rls_nodes,_)),
 4741	retractall(M:'$aleph_search'(rls_selected,_)),
 4742	setting(evalfn,Evalfn,M),
 4743	get_start_label(Evalfn,Label,M),
 4744	set(best,Label,M),
 4745	get_search_settings(S,M),
 4746	arg(4,S,SearchStrat/_),
 4747	(M:'$aleph_sat'(example,example(Num,Type)) ->
 4748		M:example(Num,Type,Example),
 4749		asserta(M:'$aleph_search'(rls_selected,selected(Label,
 4750						(Example:-true),[Num-Num],[])));
 4751		asserta(M:'$aleph_search'(rls_selected,selected(Label,
 4752						(false:-true),[],[])))
 4753	),
 4754 	asserta(M:'$aleph_search'(rls_nodes,0)),
 4755	estimate_numbers(_,M),	% so all threads can use same estimates
 4756	thread_self(Master),
 4757	message_queue_create(Queue),
 4758	create_worker_pool(N, Master, Queue, WorkerIds,M),
 4759	forall(between(1, MaxTries, R),
 4760	       thread_send_message(Queue, rls_restart(R, SearchStrat, Label,M))),
 4761	collect_results(rls_restart,MaxTries,[0,S],[Time|_],M),
 4762	kill_worker_pool(Queue, WorkerIds),
 4763 	retractall(M:'$aleph_search'(rls_restart,_)),
 4764	retract(M:'$aleph_search'(rls_nodes,Nodes)),
 4765        retract(M:'$aleph_search'(rls_selected,Selected)).
 4766
 4767rls_thread(R, SearchStrat, Label, Nodes0, selected(Best,RCl,PCov,NCov),M) :-
 4768	retractall(M:'$aleph_search'(best_refinement,_)),
 4769	retractall(M:'$aleph_search'(last_refinement,_)),
 4770        retractall(M:'$aleph_search'(rls_move,_)),
 4771        retractall(M:'$aleph_search'(rls_parentstats,_)),
 4772	retractall(M:'$aleph_search_seen'(_,_)),
 4773        asserta(M:'$aleph_search'(rls_move,1)),
 4774        asserta(M:'$aleph_search'(rls_parentstats,stats(Label,[],[]))),
 4775        p1_message('restart'), p_message(R),
 4776        find_clause(SearchStrat,M),
 4777	M:'$aleph_search'(current,current(_,Nodes0,_)),
 4778	M:'$aleph_search'(selected,selected(Best,RCl,PCov,NCov)),
 4779	retractall(M:'$aleph_search'(best_refinement,_)),
 4780	retractall(M:'$aleph_search'(last_refinement,_)),
 4781        retractall(M:'$aleph_search'(rls_move,_)),
 4782        retractall(M:'$aleph_search'(rls_parentstats,_)).
 4783
 4784
 4785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 4786% T H R E A D S
 4787
 4788create_worker_pool(N, Master, Queue, WorkerIds,M) :-
 4789	create_worker_pool(1, N, Master, Queue, WorkerIds,M).
 4790
 4791create_worker_pool(I, N, _, _, [],_M) :-
 4792	I > N, !.
 4793create_worker_pool(I, N, Master, Queue, [Id|T],M) :-
 4794	atom_concat(worker_, I, Alias),
 4795	thread_create(worker(Queue, Master,M), Id, [alias(Alias)]),
 4796	I2 is I + 1,
 4797	create_worker_pool(I2, N, Master, Queue, T,M).
 4798
 4799kill_worker_pool(Queue, WorkerIds) :-
 4800	p_message('Killing workers'),
 4801	forall(aleph_member(Worker, WorkerIds),
 4802	       kill_worker(Queue, Worker)),
 4803	p_message('Waiting for workers'),
 4804	forall(aleph_member(Worker, WorkerIds),
 4805	       thread_join(Worker, _)),
 4806	message_queue_destroy(Queue),
 4807	p_message('Ok, all done').
 4808
 4809kill_worker(Queue, Worker) :-
 4810	thread_send_message(Queue, all_done),
 4811	thread_signal(Worker, throw(surplus_to_requirements)).
 4812
 4813worker(Queue, Master,M) :-
 4814	thread_get_message(Queue, Message),
 4815	work(Message, Master,M),
 4816	worker(Queue, Master).
 4817
 4818work(rls_restart(R, SearchStrat, Label), Master,M) :-
 4819	statistics(cputime, CPU0),
 4820	rls_thread(R, SearchStrat, Label, Nodes, Selected,M),
 4821	statistics(cputime, CPU1),
 4822	CPU is CPU1 - CPU0,
 4823	thread_send_message(Master, done(CPU, Nodes, Selected)).
 4824work(all_done, _,_M) :-
 4825	thread_exit(done).
 4826
 4827collect_results(rls_restart,NResults,In,Out,M):-
 4828        collect_results(0,NResults,rls_restart,In,Out,M).
 4829
 4830collect_results(R0,MaxR,Flag,In,Out,M):-
 4831        thread_get_message(Message),
 4832        collect(Flag,Message,In,Out1,Done,M),
 4833        R1 is R0 + 1,
 4834        (   (Done == false,
 4835            R1 < MaxR)
 4836        ->  collect_results(R1,MaxR,Flag,Out1,Out)
 4837        ;   Out = Out1
 4838        ).
 4839
 4840collect(rls_restart,done(CPU, Nodes, selected(Best,RCl,PCov,NCov)),[T0,S], [T1,S],Done,M) :-
 4841        T1 is CPU + T0,
 4842        Best = [_,_,_,F|_],
 4843        M:'$aleph_search'(rls_selected,selected([_,_,_,F1|_],_,_,_)),
 4844        (F1 >= F -> true;
 4845                retract(M:'$aleph_search'(rls_selected,selected(
 4846                                                [_,_,_,F1|_],_,_,_))),
 4847                asserta(M:'$aleph_search'(rls_selected,selected(Best,
 4848                                                RCl,PCov,NCov))),
 4849                set(best,Best,M)),
 4850        setting(best,BestSoFar,M),
 4851        retract(M:'$aleph_search'(rls_nodes,Nodes1)),
 4852        Nodes2 is Nodes + Nodes1,
 4853        asserta(M:'$aleph_search'(rls_nodes,Nodes2)),
 4854        (   discontinue_search(S,BestSoFar/_,Nodes2,M)
 4855        ->  Done = true
 4856        ;   Done = false
 4857        ).
 4858
 4859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 4860% C O N T R O L
 induce_clauses(:Program:list) is det
The basic theory construction predicate. Constructs theories 1 clause at a time. /
 4868induce_clauses(M:Program):-
 4869	setting(interactive,true,M), !,
 4870	induce_incremental(M:Program).
 4871induce_clauses(M:Program):-
 4872	induce(M:Program).
 induce(:Program:list) is det
Non-interactive theory construction. Constructs theories 1 clause at a time. Does greedy cover removal after each clause found /
 4880induce(M:Program):-
 4881	clean_up(M),
 4882	set(greedy,true,M),
 4883	retractall(M:'$aleph_global'(search_stats,search_stats(_,_))),
 4884        M:'$aleph_global'(atoms_left,atoms_left(pos,PosSet)),
 4885        PosSet \= [],
 4886	store(portray_search,M),
 4887	set(portray_search,false,M),
 4888        setting(samplesize,S,M),
 4889	setting(abduce,Abduce,M),
 4890	record_settings(M),
 4891        stopwatch(StartClock),
 4892        repeat,
 4893        gen_sample(pos,S,M),
 4894
 4895	retractall(M:'$aleph_global'(besthyp,besthyp(_,_,_,_,_))),
 4896        asserta(M:'$aleph_global'(besthyp,besthyp([-inf,0,1,-inf],0,(false),[],[]))),
 4897        get_besthyp(Abduce,M),
 4898        (setting(gcws,true,M) -> sphyp(M), addgcws(M); addhyp(M)),
 4899	show_atoms_left(M),
 4900	record_atoms_left(M),
 4901        M:'$aleph_global'(atoms_left,atoms_left(pos,[])),
 4902        stopwatch(StopClock),
 4903        Time is StopClock - StartClock,
 4904		copy_theory(Program,M),
 4905		show(theory,M),
 4906        record_theory(Time,M),
 4907	noset(greedy,M),
 4908	reinstate(portray_search,M),
 4909		
 4910        p1_message('time taken'), p_message(Time), 
 4911	show_total_stats(M),
 4912	record_total_stats(M), !.
 4913
 4914copy_theory(Program,M):-
 4915	M:'$aleph_global'(rules,rules(L)),
 4916		aleph_member(ClauseNum,L),
 4917		copy_theory_inner(ClauseNum,Program,M),
 4918        aleph_member(ClauseNum,L),
 4919	M:'$aleph_global'(theory,theory(ClauseNum,_,_,_,_)).
 4920	%copy_theory_eval(ClauseNum,Program,_).
 4921copy_theory(_,_M).
 4922
 4923copy_theory_inner(ClauseNum,[SubProgram|TailP],M):-
 4924	integer(ClauseNum),
 4925	ClauseNum > 0,!,
 4926	M:'$aleph_global'(theory,theory(ClauseNum,_,SubProgram,_,_)),	
 4927	ClauseNum1 is ClauseNum-1,
 4928	copy_theory_inner(ClauseNum1,TailP,M).
 4929
 4930copy_theory_inner(0,[],_M).
 4931
 4932copy_modes(Modes,M):-
 4933	findall(mode(Mode,D),M:'$aleph_global'(mode,mode(Mode,D)),Modes).
 4934
 4935copy_constraints(Constraints,M):-
 4936	findall(Clause,M:'$aleph_good'(_,_,Clause),Constraints).
 4937
 4938copy_features(Features,M):-
 4939	findall((Head:-Body),M:'$aleph_feature'(feature,feature(_,_,_,Head,Body)),Features).
 4940
 4941% ============= UNUSED ====================
 4942copy_theory_eval(0,_,Label,M):-
 4943	M:'$aleph_global'(hypothesis,hypothesis(_,Clause,_,_)), !,
 4944	label_create(Clause,Label,M),
 4945	p_message('Rule 0'),
 4946	pp_dclause(Clause,M),
 4947	extract_count(pos,Label,PC),
 4948	extract_count(neg,Label,NC),
 4949	extract_length(Label,L),
 4950	label_print_eval([PC,NC,L]),
 4951	nl.
 4952copy_theory_eval(ClauseNum,Program,_,M):-
 4953	integer(ClauseNum),
 4954	ClauseNum > 0,
 4955	M:'$aleph_global'(theory,theory(ClauseNum,_,Clause,_,_)),
 4956	!,
 4957	copy_theory_eval_inner(Clause,Program).
 4958copy_theory_eval(_,_,_,_M).
 4959copy_theory_eval_inner((H:-true),Program):-
 4960	!,
 4961	copy_theory_eval_inner(H,Program).
 4962copy_theory_eval_inner((H:-B),Program):-
 4963	!,
 4964    copy_term((H:-B),(Head:-Body)),
 4965    numbervars((Head:-Body),0,_),
 4966	add_lit_to_program(Body,Program).
 4967copy_theory_eval_inner((Lit),Program):- 
 4968	!,
 4969	copy_term(Lit,Lit1),
 4970    numbervars(Lit1,0,_),
 4971	add_lit_to_program(Lit1,Program).
 4972
 4973add_lit_to_program((Lit,Lits),[Lit|Program1]):-
 4974	add_lit_to_program(Lits,Program1).
 4975add_lit_to_program((Lit),[Lit]).
 4976
 4977% ============= /UNUSED ====================
 induce_max(:Program:list) is det
Construct theories 1 clause at a time. Does not perform greedy cover removal after each clause found. Constructs unique maximum cover set'' solution by obtaining the best clause covering each example /
 4986% slow
 4987induce_max(M:Program):-
 4988	clean_up(M),
 4989	retractall(M:'$aleph_global'(search_stats,search_stats(_,_))),
 4990	M:'$aleph_global'(atoms,atoms(pos,PosSet)),
 4991	PosSet \= [],
 4992	store(portray_search,M),
 4993	set(portray_search,false,M),
 4994	record_settings(M),
 4995	stopwatch(StartClock),
 4996	set(maxcover,true,M),
 4997	aleph_induce_max(PosSet,M),
 4998	stopwatch(StopClock),
 4999	Time is StopClock - StartClock,
 5000	copy_theory(Program,M),
 5001	show(theory,M),
 5002	record_theory(Time,M),
 5003	noset(maxcover,M),
 5004	reinstate(portray_search,M),
 5005	reinstate(greedy,M),
 5006	p1_message('time taken'), p_message(Time),
 5007	show_total_stats(M),
 5008	record_total_stats(M), !.
 5009
 5010aleph_induce_max([],_M).
 5011aleph_induce_max([Start-Finish|Intervals],M):-
 5012	asserta(M:'$aleph_local'(counter,Start)),
 5013	induce_max1(Finish,M),
 5014	aleph_induce_max(Intervals,M).
 5015
 5016induce_max1(Finish,M):-
 5017        M:'$aleph_local'(counter,S),
 5018        S =< Finish, !,
 5019	(setting(resample,Resample,M) -> true; Resample = 1),
 5020        repeat,
 5021        retract(M:'$aleph_local'(counter,Start)),
 5022	gen_sample(Resample,pos,Start,M),
 5023	get_besthyp(false,M),
 5024        update_coverset(pos,Start,M),
 5025        Next is Start+1,
 5026        assertz(M:'$aleph_local'(counter,Next)),
 5027        Next > Finish, !,
 5028	retract(M:'$aleph_local'(counter,Next)).
 5029induce_max1(_,_).
 induce_cover(:Program:list) is det
Construct theories 1 clause at a time. Does not perform greedy cover removal after each clause found. /
 5037induce_cover(M:Program):-
 5038	clean_up(M),
 5039	retractall(M:'$aleph_global'(search_stats,search_stats(_,_))),
 5040	M:'$aleph_global'(atoms,atoms(pos,PosSet)),
 5041	PosSet \= [],
 5042	store(portray_search,M),
 5043	set(portray_search,false,M),
 5044	setting(samplesize,S,M),
 5045	setting(abduce,Abduce,M),
 5046	record_settings(M),
 5047	stopwatch(StartClock),
 5048        repeat,
 5049	gen_sample(pos,S,M),
 5050	asserta(M:'$aleph_global'(besthyp,besthyp([-inf,0,1,-inf],0,
 5051					(false),[],[]))),
 5052	get_besthyp(Abduce,M),
 5053	addhyp(M),
 5054        M:'$aleph_global'(atoms_left,atoms_left(pos,[])),
 5055	stopwatch(StopClock),
 5056	Time is StopClock - StartClock,
 5057	copy_theory(Program,M),
 5058	show(theory,M),
 5059	record_theory(Time,M),
 5060	reinstate(portray_search,M),
 5061	reinstate(greedy,M),
 5062	p1_message('time taken'), p_message(Time), 
 5063	show_total_stats(M),
 5064	record_total_stats(M), !.
 induce_incremental(:Program:list) is det
Rudimentary version of an interactive, incremental rule learner.
  1. ask the user for an example default is to use a new positive example from previous search if user responds with Ctrl-d (eof) then search stops if user responds with "ok" then default is used otherwise user has to provide an example
  2. construct bottom clause using that example expects to have appropriate mode declarations
  3. search for the best clause C
  4. ask the user about C who can respond with
    • ok: clause added to theory
    • prune: statement added to prevent future clauses that are subsumed by C
    • overgeneral: constraint added to prevent future clauses that subsume C
    • overgeneral because not(E): E is added as a negative example
    • overspecific: C is added as new positive example
    • overspecific because E: E is added as a new positive example
    • X: where X is some aleph command like "covers"
    • Ctrl-d (eof): return to Step 1

/

 5092induce_incremental(M:Program):-
 5093	clean_up(M),
 5094	retractall(M:'$aleph_global'(search_stats,search_stats(_,_))),
 5095	store_values([interactive,portray_search,proof_strategy,mode],M),
 5096	set(portray_search,false,M),
 5097	set(proof_strategy,sld,M),
 5098	set(interactive,true,M),
 5099	record_settings(M),
 5100        stopwatch(StartClock),
 5101        repeat,
 5102	ask_example_web(E,M),
 5103	((E = end_of_file; E = none) -> true;
 5104		once(record_example(check,pos,E,N,M)),
 5105		retractall(M:'$aleph_global'(example_selected,
 5106						example_selected(_,_))),
 5107        	asserta(M:'$aleph_global'(example_selected,
 5108						example_selected(pos,N))),
 5109		once(sat(N,M)),
 5110		once(reduce(M:_)),
 5111		once(process_hypothesis_web(M)),
 5112		fail),
 5113	!,
 5114        stopwatch(StopClock),
 5115        Time is StopClock - StartClock,
 5116		copy_theory(Program0,M),
 5117		reverse(Program0,Program),
 5118        show(theory,M),
 5119	show(pos,M),
 5120	show(neg,M),
 5121	show(aleph_false/0,M),
 5122	show(prune/1,M),
 5123        record_theory(Time,M),
 5124	reinstate_values([interactive,portray_search,proof_strategy,mode],M),
 5125        p1_message('time taken'), p_message(Time).
 induce_theory(:Program:list) is det
does theory-level search currently only with search = rls; and evalfn = accuracy induce entire theories from batch data using a randomised local search currently, this can use either: simulated annealing with a fixed temp, GSAT, or a WSAT-like algorithm the choice of these is specified by the parameter: rls_type all methods employ random multiple restarts and a limit on the number of moves the number of restarts is specified by aleph_set(tries,...) the number of moves is specified by aleph_set(moves,...) annealing currently restricted to using a fixed temperature the temperature is specified by aleph_set(temperature,...) the fixed temp. makes it equivalent to the Metropolis alg. WSAT requires a random-walk probability'' the walk probability is specified by aleph_set(walk,...) a walk probability of 0 is equivalent to doing standard GSAT theory accuracy is the evaluation function /
 5151aleph_induce_theory(rls,M):-
 5152	clean_up(M),
 5153	retractall(M:'$aleph_global'(search_stats,search_stats(_,_))),
 5154        store(evalfn,M),
 5155        set(evalfn,accuracy,M),
 5156	record_settings(M),
 5157	find_theory(rls,_,M),
 5158        reinstate(evalfn,M),
 5159	show_total_stats(M),
 5160	record_total_stats(M), !.
 5161aleph_induce_theory(_,_M).
 5162
 5163aleph_induce_theory(rls,Program,M):-
 5164	clean_up(M),
 5165	retractall(M:'$aleph_global'(search_stats,search_stats(_,_))),
 5166        store(evalfn,M),
 5167        set(evalfn,accuracy,M),
 5168	record_settings(M),
 5169	find_theory(rls,Program,M),
 5170        reinstate(evalfn,M),
 5171	show_total_stats(M),
 5172	record_total_stats(M), !.
 5173
 5174induce_theory(M:Program):-
 5175	setting(search,Search,M),
 5176	aleph_induce_theory(Search,Program,M).
 induce_constraints(:Constraints:list) is det
search for logical constraints that hold in the background knowledge A constraint is a clause of the form aleph_false:-... This is modelled on the Claudien program developed by L. De Raedt and his colleagues in Leuven Constraints that are nearly true'' can be obtained by altering the noise setting All constraints found are stored as `good clauses'. /
 5191induce_constraints(M:Constraints):-
 5192	clean_up(M),
 5193	retractall(M:'$aleph_global'(search_stats,search_stats(_,_))),
 5194	store_values([portray_search,search,construct_bottom,good,goodfile],M),
 5195	noset(goodfile,M),
 5196	set(portray_search,false,M),
 5197	set(construct_bottom,false,M),
 5198	set(search,ic,M),
 5199	set(good,true,M),
 5200	sat(uspec,0,M),
 5201	reduce(M:_),
 5202	copy_constraints(Constraints,M),
 5203	show(constraints,M),
 5204	reinstate_values([portray_search,search,construct_bottom,good,goodfile],M),
 5205	show_total_stats(M),
 5206	record_total_stats(M), !.
 induce_modes(:Modes:list) is det
search for an acceptable set of mode declarations /
 5214induce_modes(M:Modes):-
 5215	clean_up(M),
 5216	store_values([typeoverlap],M),
 5217	search_modes(M),
 5218	reinstate_values([typeoverlap],M),
 5219	copy_modes(Modes,M),
 5220	show(modes,M),!.
 induce_features(:Features:list) is det
search for interesting boolean features each good clause found in a search constitutes a new boolean feature the maximum number of features is controlled by aleph_set(max_features,F) the features are constructed by doing the following: while (number of features =< F) do:
  1. randomly select an example;
  2. search for good clauses using the example selected;
  3. construct new features using good clauses

/

 5233induce_features(M:Features):-
 5234	clean_up(M),
 5235	store_values([good,check_good,updateback,construct_features,samplesize,greedy,explore,lazy_on_contradiction],M),
 5236	set(good,true,M),
 5237	set(check_good,true,M),
 5238	set(updateback,false,M),
 5239	set(construct_features,true,M),
 5240	set(lazy_on_contradiction,true,M),
 5241	(setting(feature_construction,exhaustive,M) -> set(explore,true,M);
 5242			true),
 5243	setting(max_features,FMax,M),
 5244        record_settings(M),
 5245        stopwatch(StartClock),
 5246        M:'$aleph_global'(atoms_left,atoms_left(pos,AtomsLeft)), 
 5247	repeat,
 5248        gen_sample(pos,0,M),
 5249	retractall(M:'$aleph_global'(besthyp,besthyp(_,_,_,_,_))),
 5250        asserta(M:'$aleph_global'(besthyp,besthyp([-inf,0,1,-inf],0,(false),[],[]))),
 5251        get_besthyp(false,M),
 5252        addhyp(M),
 5253	show_atoms_left(M),
 5254	record_atoms_left(M),
 5255        ((M:'$aleph_search'(last_good,LastGood), LastGood >= FMax);
 5256        	M:'$aleph_global'(atoms_left,atoms_left(pos,[]))), !,
 5257	gen_features(M),
 5258        stopwatch(StopClock),
 5259        Time is StopClock - StartClock,
 5260	copy_features(Features,M),
 5261	show(features,M),
 5262        record_features(Time,M),
 5263        retract(M:'$aleph_global'(atoms_left,atoms_left(pos,_))), 
 5264        assertz(M:'$aleph_global'(atoms_left,atoms_left(pos,AtomsLeft))), 
 5265        reinstate_values([good,check_good,updateback,construct_features,samplesize,greedy,explore,lazy_on_contradiction],M), !.
 induce_tree(:Tree:list) is det
construct a theory using recursive partitioning. rules are obtained by building a tree the tree constructed can be one of 4 types classification, regression, class_probability or model the type is set by aleph_set(tree_type,...) In addition, the following parameters are relevant

The basic procedure attempts to construct a tree to predict the dependent variable in the examples. Note that the mode declarations must specify the variable as an output argument. Paths from root to leaf constitute clauses. Tree-construction is viewed as a refinement operation: any leaf can currently be refined by extending the corresponding clause. The extension is done using Aleph's automatic refinement operator that extends clauses within the mode language. A lookahead option allows additions to include several literals. Classification problems currently use entropy gain to measure worth of additions. Regression and model trees use reduction in standard deviation to measure worth of additions. This is not quite correct for the latter. Pruning for classification is done on the final set of clauses from the tree. The technique used here is the reduced-error pruning method. For classification trees, this is identical to the one proposed by Quinlan in C4.5: Programs for Machine Learning, Morgan Kauffmann. For regression and model trees, this is done by using a pessimistic estimate of the sample standard deviation. This assumes normality of observed values in a leaf. This method and others have been studied by L. Torgo in "A Comparative Study of Reliable Error Estimators for Pruning Regression Trees" Following work by F Provost and P Domingos, pruning is not employed for class probability prediction. Currently no pruning is performed for model trees. /

 5309induce_tree(M:Program):-
 5310	clean_up(M),
 5311	setting(tree_type,Type,M),
 5312	store_values([refine],M),
 5313	set(refine,auto,M),
 5314	setting(mingain,MinGain,M),
 5315	(MinGain =< 0.0 ->
 5316		err_message('inappropriate setting for mingain'),
 5317		fail;
 5318		true
 5319	),
 5320	record_settings(M),
 5321	stopwatch(StartClock),
 5322	construct_tree(Type,M),
 5323	stopwatch(StopClock),
 5324	Time is StopClock - StartClock,
 5325	copy_theory(Program0,M),
 5326	reverse(Program0,Program),
 5327	show(theory,M),
 5328	record_theory(Time,M),
 5329	reinstate_values([refine],M), !.
 5330% utilities for the induce predicates
 5331
 5332
 5333% randomly pick a positive example and construct bottom clause
 5334%	example is from those uncovered by current theory
 5335%	and whose bottom clause has not been stored away previously
 5336% 	makes at most 100 attempts to find such an example
 5337rsat(M):-
 5338        M:'$aleph_global'(atoms_left,atoms_left(pos,PosSet)),
 5339        PosSet \= [],
 5340	store(resample,M),
 5341	set(resample,1,M),
 5342	rsat(100,M),
 5343	reinstate(resample,M).
 5344
 5345rsat(0,_M):- !.
 5346rsat(N,M):-
 5347        gen_sample(pos,1,M),
 5348	M:'$aleph_global'(example_selected,example_selected(pos,Num)),
 5349	(\+(M:'$aleph_sat'(stored,stored(Num,pos,_))) ->
 5350		!,
 5351		retract(M:'$aleph_global'(example_selected,
 5352					example_selected(pos,Num))),
 5353		sat(pos,Num,M);
 5354		N1 is N - 1,
 5355		rsat(N1,M)).
 5356
 5357get_besthyp(AbduceFlag,M):-
 5358	retract(M:'$aleph_global'(example_selected,
 5359				example_selected(pos,Num))),
 5360	reset_best_label(M),	 % set-up target to beat
 5361	sat(Num,M),
 5362	reduce(M:_),
 5363	update_besthyp(Num,M),
 5364	(AbduceFlag = true ->
 5365        	M:example(Num,pos,Atom),
 5366		abgen(Atom,AbGen,M),
 5367		once(retract(M:'$aleph_global'(hypothesis,
 5368				hypothesis(Label,_,PCover,NCover)))),
 5369		assert(M:'$aleph_global'(hypothesis,
 5370				hypothesis(Label,AbGen,PCover,NCover))),
 5371		update_besthyp(Num,M);
 5372		true),
 5373	fail.
 5374get_besthyp(_,M):-
 5375        retract(M:'$aleph_global'(besthyp,besthyp(L,Num,H,PC,NC))),
 5376	H \= false, !,
 5377	((setting(samplesize,S,M),S>1)->
 5378		setting(nodes,Nodes,M),
 5379		show_clause(sample,L,H,Nodes,M),
 5380		record_clause(sample,L,H,Nodes,M);
 5381		true),
 5382        add_hyp(L,H,PC,NC,M),
 5383	asserta(M:'$aleph_global'(example_selected,
 5384				example_selected(pos,Num))), !.
 5385get_besthyp(_,_M).
 5386
 5387
 5388reset_best_label(M):-
 5389	M:'$aleph_global'(besthyp,besthyp(Label1,_,Clause,P,N)),
 5390	M:'$aleph_search'(best_label,Label/_),
 5391	Label = [_,_,L,GainE|_],
 5392	Label1 = [_,_,L1,Gain1E|_],
 5393        % Gain > Gain1, !,
 5394	arithmetic_expression_value(GainE,Gain),
 5395	arithmetic_expression_value(Gain1E,Gain1),
 5396        ((Gain1 > Gain);(Gain1 =:= Gain, L1 < L)), !,
 5397	retract(M:'$aleph_search'(best_label,Label/_)),
 5398	asserta(M:'$aleph_search'(best_label,Label1/0)),
 5399	retractall(M:'$aleph_search'(selected,_)),
 5400	asserta(M:'$aleph_search'(selected,selected(Label1,Clause,P,N))).
 5401reset_best_label(_M).
 5402
 5403
 5404update_besthyp(Num,M):-
 5405	M:'$aleph_global'(hypothesis,hypothesis(Label,H,PCover,NCover)),
 5406	M:'$aleph_global'(besthyp,besthyp(Label1,_,_,_,_)),
 5407	Label = [_,_,L,GainE|_],
 5408	Label1 = [_,_,L1,Gain1E|_],
 5409        % Gain > Gain1, !,
 5410	arithmetic_expression_value(GainE,Gain),
 5411	arithmetic_expression_value(Gain1E,Gain1),
 5412        ((Gain > Gain1);(Gain =:= Gain1, L < L1)), !,
 5413	retract(M:'$aleph_global'(besthyp,besthyp(Label1,_,_,_,_))),
 5414	assertz(M:'$aleph_global'(besthyp,besthyp(Label,Num,H,PCover,NCover))).
 5415update_besthyp(_,_M).
 5416
 5417
 5418% generate a new feature from a good clause
 5419gen_features(M):-
 5420	aleph_abolish('$aleph_feature'/2,M),
 5421	(setting(dependent,PredictArg,M) -> true; PredictArg is 0),
 5422        (setting(minscore,FMin,M) -> true; FMin = -inf),
 5423	M:'$aleph_good'(_,Label,Clause),
 5424	Label = [_,_,_,FE|_],
 5425	arithmetic_expression_value(FE,F),
 5426	F >= FMin,
 5427	split_clause(Clause,Head,Body),
 5428	Body \= true,
 5429	functor(Head,Name,Arity),
 5430	functor(Template,Name,Arity),
 5431	copy_iargs(Arity,Head,Template,PredictArg),
 5432	get_feature_class(PredictArg,Head,Body,Class,M),
 5433	gen_feature((Template:-Body),Label,Class,M),
 5434	fail.
 5435gen_features(M):-
 5436	(setting(dependent,PredictArg,M) -> true; PredictArg is 0),
 5437	setting(good,true,M),
 5438	setting(goodfile,File,M),
 5439	aleph_open(File,read,Stream),
 5440        (setting(minscore,FMin,M) -> true; FMin = -inf),
 5441	repeat,
 5442	read(Stream,Fact),
 5443	(Fact = M:'$aleph_good'(_,Label,Clause) ->
 5444		Label = [_,_,_,FE|_],
 5445		arithmetic_expression_value(FE,F),
 5446		F >= FMin,
 5447		split_clause(Clause,Head,Body),
 5448		Body \= true,
 5449		functor(Head,Name,Arity),
 5450		functor(Template,Name,Arity),
 5451		copy_iargs(Arity,Head,Template,PredictArg),
 5452		get_feature_class(PredictArg,Head,Body,Class,M),
 5453		gen_feature((Template:-Body),Label,Class,M),
 5454		fail;
 5455		close(Stream), !
 5456	).
 5457gen_features(_M).
 5458
 5459get_feature_class(Argno,Head,Body,Class,M):-
 5460	has_class(Argno,Head,Body,Class,M), !.
 5461get_feature_class(_,_,_,_,_M).
 5462
 5463has_class(Argno,Head,_,Class,_M):-
 5464	arg(Argno,Head,Class),
 5465	ground(Class), !.
 5466has_class(Argno,Head,Body,Class,M):-
 5467	arg(Argno,Head,DepVar),
 5468	in((DepVar=Class),Body,M), 
 5469	ground(Class), !.
 5470
 5471ask_example(E,M):-
 5472	(M:'$aleph_global'(example_selected,example_selected(pos,N)) ->
 5473		M:example(N,pos,E1);
 5474		E1 = none),
 5475	!,
 5476	show_options(example_selection),
 5477	tab(4),
 5478	write('Response '), p1_message(default:E1), write('?'), nl,
 5479	read(Response),
 5480	(Response = ok  -> E = E1; E = Response).
 5481
 5482ask_example_web(E,M):-
 5483	(M:'$aleph_global'(example_selected,example_selected(pos,N)) ->
 5484		M:example(N,pos,E1);
 5485		E1 = none),
 5486	!,
 5487	show_options_web(example_selection),
 5488	tab(4),
 5489	write('Response '), p1_message(default:E1), write('?'), nl,
 5490	read(Response),
 5491	(Response = ok  -> E = E1; E = Response).
 5492
 5493process_hypothesis(M):-
 5494	show(hypothesis,M),
 5495	repeat,
 5496	show_options(hypothesis_selection),
 5497	tab(4),
 5498	write('Response?'), nl,
 5499	read(Response),
 5500	process_hypothesis(Response,M),
 5501	(Response = end_of_file; Response = none), !.
 5502
 5503process_hypothesis_web(M):-
 5504	show(hypothesis,M),
 5505	repeat,
 5506	show_options_web(hypothesis_selection),
 5507	tab(4),
 5508	write('Response?'), nl,
 5509	read(Response),
 5510	process_hypothesis(Response,M),
 5511	(Response = end_of_file; Response = none), !.
 5512
 5513process_hypothesis(end_of_file,_M):-
 5514	nl, nl, !.
 5515process_hypothesis(none,_M):-
 5516	nl, nl, !.
 5517process_hypothesis(ok,M):-
 5518	!,
 5519	update_theory(_,M),
 5520	nl, p_message('added new clause').
 5521process_hypothesis(prune,M):-
 5522        !,
 5523        retract(M:'$aleph_global'(hypothesis,hypothesis(_,H,_,_))),
 5524        Prune = (
 5525                hypothesis(Head,Body,_,M),
 5526                goals_to_list(Body,BodyL),
 5527                clause_to_list(H,HL),
 5528                aleph_subsumes(HL,[Head|BodyL])),
 5529        assertz(M:(prune(H):- Prune)),
 5530        nl, p_message('added new prune statement').
 5531process_hypothesis(overgeneral,M):-
 5532        !,
 5533        retract(M:'$aleph_global'(hypothesis,hypothesis(_,H,_,_))),
 5534        Constraint = (
 5535                hypothesis(Head,Body,_,M),
 5536                goals_to_list(Body,BodyL),
 5537                clause_to_list(H,HL),
 5538                aleph_subsumes([Head|BodyL],HL)),
 5539        assertz(M:(aleph_false:- Constraint)),
 5540        nl, p_message('added new constraint'). 
 5541process_hypothesis(overgeneral because not(E),M):-
 5542	!,
 5543	record_example(check,neg,E,_,M),
 5544	nl, p_message('added new negative example').
 5545process_hypothesis(overspecific,M):-
 5546	!,
 5547        retract(M:'$aleph_global'(hypothesis,hypothesis(_,H,_,_))),
 5548	(retract(M:'$aleph_global'(example_selected,example_selected(_,_)))->
 5549		true;
 5550		true),
 5551	record_example(check,pos,H,N,M),
 5552	asserta(M:'$aleph_global'(example_selected,example_selected(pos,N))),
 5553	nl, p_message('added new positive example').
 5554process_hypothesis(overspecific because E,M):-
 5555	!,
 5556        retract(M:'$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
 5557	(retract(M:'$aleph_global'(example_selected,example_selected(_,_)))->
 5558		true;
 5559		true),
 5560	record_example(check,pos,E,N,M),
 5561	asserta(M:'$aleph_global'(example_selected,example_selected(pos,N))),
 5562	nl, p_message('added new positive example').
 5563process_hypothesis(AlephCommand,M):-
 5564	M:AlephCommand.
 5565
 5566show_options(example_selection):-
 5567	nl,
 5568	tab(4),
 5569	write('Options:'), nl,
 5570	tab(8),
 5571	write('-> "ok." to accept default example'), nl,
 5572	tab(8),
 5573	write('-> Enter an example'), nl, 
 5574	tab(8),
 5575	write('-> ctrl-D or "none." to end'), nl, nl.
 5576show_options(hypothesis_selection):-
 5577	nl,
 5578	tab(4),
 5579	write('Options:'), nl,
 5580	tab(8),
 5581	write('-> "ok." to accept clause'), nl,
 5582	tab(8),
 5583        write('-> "prune." to prune clause and its refinements from the search'), nl,
 5584        tab(8),
 5585	write('-> "overgeneral." to add clause as a constraint'), nl, 
 5586	tab(8),
 5587	write('-> "overgeneral because not(E)." to add E as a negative example'), nl, 
 5588	tab(8),
 5589	write('-> "overspecific." to add clause as a positive example'), nl, 
 5590	tab(8),
 5591	write('-> "overspecific because E." to add E as a positive example'), nl, 
 5592	tab(8),
 5593	write('-> any Aleph command'), nl, 
 5594	tab(8),
 5595	write('-> "ctrl-D or "none." to end'), nl, nl.
 5596
 5597show_options_web(example_selection):-
 5598	nl,
 5599	tab(4),
 5600	write('Options:'), nl,
 5601	tab(8),
 5602	write('-> "ok." to accept default example'), nl,
 5603	tab(8),
 5604	write('-> Enter an example'), nl, 
 5605	tab(8),
 5606	write('-> "none." to end'), nl, nl.
 5607show_options_web(hypothesis_selection):-
 5608	nl,
 5609	tab(4),
 5610	write('Options:'), nl,
 5611	tab(8),
 5612	write('-> "ok." to accept clause'), nl,
 5613	tab(8),
 5614    write('-> "prune." to prune clause and its refinements from the search'), nl,
 5615    tab(8),
 5616	write('-> "overgeneral." to add clause as a constraint'), nl, 
 5617	tab(8),
 5618	write('-> "overgeneral because not(E)." to add E as a negative example'), nl, 
 5619	tab(8),
 5620	write('-> "overspecific." to add clause as a positive example'), nl, 
 5621	tab(8),
 5622	write('-> "overspecific because E." to add E as a positive example'), nl, 
 5623	tab(8),
 5624	write('-> any Aleph command'), nl, 
 5625	tab(8),
 5626	write('-> "none." to end'), nl, nl.
 5627	
 5628
 5629get_performance(M):-
 5630	setting(evalfn,Evalfn,M),
 5631	(Evalfn = sd; Evalfn = mse), !.
 5632get_performance(M):-
 5633	findall(Example,M:example(_,pos,Example),Pos),
 5634	findall(Example,M:example(_,neg,Example),Neg),
 5635	(test_ex(Pos,noshow,Tp,TotPos,M)->
 5636		Fn is TotPos - Tp;
 5637		TotPos = 0, Tp = 0, Fn = 0),
 5638	(test_ex(Neg,noshow,Fp,TotNeg,M)->
 5639		Tn is TotNeg - Fp;
 5640		TotNeg = 0, Tn = 0, Fp = 0),
 5641	TotPos + TotNeg > 0,
 5642	p_message('Training set performance'),
 5643	write_cmatrix([Tp,Fp,Fn,Tn]),
 5644	p1_message('Training set summary'), p_message([Tp,Fp,Fn,Tn]),
 5645	fail.
 5646get_performance(M):-
 5647	(setting(test_pos,PFile,M) ->
 5648		test(PFile,noshow,Tp,TotPos,M),
 5649		Fn is TotPos - Tp;
 5650		TotPos = 0, Tp = 0, Fn = 0),
 5651	(setting(test_neg,NFile,M) ->
 5652		test(NFile,noshow,Fp,TotNeg,M),
 5653		Tn is TotNeg - Fp;
 5654		TotNeg = 0, Tn = 0, Fp = 0),
 5655	TotPos + TotNeg > 0,
 5656	p_message('Test set performance'),
 5657	write_cmatrix([Tp,Fp,Fn,Tn]),
 5658	p1_message('Test set summary'), p_message([Tp,Fp,Fn,Tn]),
 5659	fail.
 5660get_performance(_M).
 5661
 5662write_cmatrix([Tp,Fp,Fn,Tn]):-
 5663        P is Tp + Fn, N is Fp + Tn,
 5664        PP is Tp + Fp, PN is Fn + Tn,
 5665        Total is PP + PN,
 5666        (Total = 0 -> Accuracy is 0.5; Accuracy is (Tp + Tn)/Total),
 5667        find_max_width([Tp,Fp,Fn,Tn,P,N,PP,PN,Total],0,W1),
 5668        W is W1 + 2,
 5669        tab(5), write(' '), tab(W), write('Actual'), nl,
 5670        tab(5), write(' '), write_entry(W,'+'), tab(6), write_entry(W,'-'), nl,
 5671        tab(5), write('+'),
 5672        write_entry(W,Tp), tab(6), write_entry(W,Fp), tab(6), write_entry(W,PP), nl,
 5673        write('Pred '), nl,
 5674        tab(5), write('-'),
 5675        write_entry(W,Fn), tab(6), write_entry(W,Tn), tab(6), write_entry(W,PN), nl, nl,
 5676        tab(5), write(' '), write_entry(W,P), tab(6), write_entry(W,N),
 5677        tab(6), write_entry(W,Total), nl, nl,
 5678        write('Accuracy = '), write(Accuracy), nl.
 5679
 5680 
 5681find_max_width([],W,W).
 5682find_max_width([V|T],W1,W):-
 5683        name(V,VList),
 5684        length(VList,VL),
 5685        (VL > W1 -> find_max_width(T,VL,W);
 5686                find_max_width(T,W1,W)).
 5687 
 5688write_entry(W,V):-
 5689        name(V,VList),
 5690        length(VList,VL),
 5691        Y is integer((W-VL)/2),
 5692        tab(Y), write(V), tab(Y).
 5693
 5694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 5695% A B D U C T I O N
 5696
 5697% Generalisation of an abductive explanation for a fact.
 5698% The basic procedure is a simplified variant of S. Moyle's Alecto
 5699% program. Alecto is described in some detail in S. Moyle,
 5700% "Using Theory Completion to Learn a Navigation Control Program",
 5701% Proceedings of the Twelfth International Conference on ILP (ILP2002),
 5702% S. Matwin and C.A. Sammut (Eds), LNAI 2583, pp 182-197,
 5703% 2003.  
 5704% Alecto does the following: for each positive example,  an
 5705% abductive explanation is obtained. This explanation is set of
 5706% ground atoms. The union of abductive explanations from all
 5707% positive examples is formed (this is also a set of ground atoms).
 5708% These are then generalised to give the final theory. The
 5709% ground atoms in an abductive explanation are obtained using
 5710% Yamamoto's SOLD resolution or SOLDR (Skip Ordered Linear resolution for
 5711% Definite clauses). 
 5712% One complication with abductive learning is this: for a given
 5713% positive example to be provable, we require all the ground atoms
 5714% in its abductive explanation to be true. Correctly therefore,
 5715% we would need to assert the abductive explanation before
 5716% checking the utility of any hypothesis. To avoid unnecessary
 5717% asserts and retracts, the "pclause" trick is used here (see
 5718% record_testclause/0).
 5719
 5720abgen(Fact,M):-
 5721	abgen(Fact,_,M).
 5722	
 5723abgen(Fact,AbGen,M):-
 5724	retractall(M:'$aleph_search'(abgenhyp,hypothesis(_,_,_,_))),
 5725	Minf is -inf,
 5726	asserta(M:'$aleph_search'(abgenhyp,
 5727				hypothesis([Minf,0,1,Minf],[false],[],[]))),
 5728	setting(max_abducibles,Max,M),
 5729	abgen(Fact,Max,AbGen,M),
 5730	M:'$aleph_global'(hypothesis,hypothesis(Label,_,PCover,NCover)),
 5731	Label = [_,_,LE,GainE|_],
 5732	arithmetic_expression_value(LE,L),
 5733	arithmetic_expression_value(GainE,Gain),
 5734	M:'$aleph_search'(abgenhyp,hypothesis(Label1,_,_,_)),
 5735	Label1 = [_,_,L1E,Gain1E|_],
 5736	arithmetic_expression_value(L1E,L1),
 5737	arithmetic_expression_value(Gain1E,Gain1),
 5738	once(((Gain > Gain1); (Gain =:= Gain1, L < L1))),
 5739	once(retract(M:'$aleph_search'(abgenhyp,hypothesis(_,_,_,_)))),
 5740	asserta(M:'$aleph_search'(abgenhyp,
 5741			hypothesis(Label,AbGen,PCover,NCover))),
 5742	fail.
 5743abgen(_,AbGen,M):-
 5744	retractall(M:'$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
 5745	M:'$aleph_search'(abgenhyp,hypothesis(Label,AbGen,PCover,NCover)),
 5746	asserta(M:'$aleph_global'(hypothesis,
 5747			hypothesis(Label,AbGen,PCover,NCover))).
 5748
 5749abgen(Fact,Max,AbGen,M):-
 5750	sold_prove(Fact,AbAtoms,M),
 5751	ground(AbAtoms),
 5752	length(AbAtoms,N),
 5753	N =< Max,
 5754	prolog_type(Prolog),
 5755	(Prolog = yap ->
 5756		store_abduced_atoms(AbAtoms,AssertRefs,M);
 5757		store_abduced_atoms(AbAtoms,M)),
 5758	store(proof_strategy,M),
 5759	set(proof_strategy,sld,M),
 5760	gen_abduced_atoms(AbAtoms,AbGen,M),
 5761	reinstate(proof_strategy,M),
 5762	(Prolog = yap ->
 5763		erase_refs(AssertRefs);
 5764		remove_abduced_atoms(AbAtoms,M)).
 5765
 5766gen_abduced_atoms([],[],_M).
 5767gen_abduced_atoms([AbAtom|AbAtoms],[AbGen|AbGens],M):-
 5768	functor(AbAtom,Name,Arity),
 5769	add_determinations(Name/Arity,true,M),
 5770	sat(AbAtom,M),
 5771	reduce(M:_),
 5772	M:'$aleph_global'(hypothesis,hypothesis(_,AbGen,_,_)),
 5773	remove_explained(AbAtoms,AbGen,AbAtoms1,M),
 5774	gen_abduced_atoms(AbAtoms1,AbGens,M).
 5775
 5776remove_explained([],_,[],_M).
 5777remove_explained([AbAtom|AbAtoms],(Head:-Body),Rest,M):-
 5778	\+((\+ M:((AbAtom = Head), Body))), !,
 5779	remove_explained(AbAtoms,(Head:-Body),Rest,M).
 5780remove_explained([AbAtom|AbAtoms],(Head:-Body),[AbAtom|Rest],M):-
 5781	remove_explained(AbAtoms,(Head:-Body),Rest,M).
 5782	
 5783store_abduced_atoms([],[],_M).
 5784store_abduced_atoms([AbAtom|AbAtoms],[DbRef|DbRefs],M):-
 5785	assertz(M:'$aleph_search'(abduced,pclause(AbAtom,true)),DbRef),
 5786	store_abduced_atoms(AbAtoms,DbRefs,M).
 5787
 5788store_abduced_atoms([],_M).
 5789store_abduced_atoms([AbAtom|AbAtoms],M):-
 5790	assertz(M:'$aleph_search'(abduced,pclause(AbAtom,true))),
 5791	store_abduced_atoms(AbAtoms,M).
 5792
 5793remove_abduced_atoms([],_M).
 5794remove_abduced_atoms([AbAtom|AbAtoms],M):-
 5795	retract(M:'$aleph_search'(abduced,pclause(AbAtom,true))),
 5796	remove_abduced_atoms(AbAtoms,M).
 5797
 5798
 5799%    sold_prove(+G,-A)
 5800% Where G is an input goal (comma separated conjunction of atoms)
 5801% and A is a list of atoms (containing the abductive explanation).
 5802% This procedure is due to S.Moyle
 5803sold_prove(Goal,SkippedGoals,M):-
 5804	soldnf_solve(Goal,Skipped,M),
 5805	sort(Skipped,SkippedGoals).
 5806
 5807soldnf_solve(Goal,Skipped,M):-
 5808	soldnf_solve(Goal,true,[],Skipped,M).    
 5809
 5810soldnf_solve((Goal,Goals),Status,SkippedSoFar,Skipped,M):-
 5811	!,
 5812	soldnf_solve(Goal,Status1,SkippedSoFar,Skipped1,M),
 5813	soldnf_solve(Goals,Status2,Skipped1,Skipped,M),
 5814	conj_status(Status1,Status2,Status).
 5815soldnf_solve(not(Goal),true,SkippedSoFar,Skipped,M):-
 5816	soldnf_solve(Goal,false,SkippedSoFar,Skipped,M).
 5817soldnf_solve(not(Goal),false,SkippedSoFar,Skipped,M):-
 5818	!,
 5819	soldnf_solve(Goal,true,SkippedSoFar,Skipped,M).
 5820soldnf_solve(Goal,Status,SkippedSoFar,SkippedSoFar,M):-
 5821	soldnf_builtin(Goal,M), !,
 5822	soldnfcall(Goal,Status,M).
 5823soldnf_solve(Goal,Status,SkippedSoFar,Skipped,M):-
 5824	soldnf_clause(Goal,Body,M),
 5825	soldnf_solve(Body,Status,SkippedSoFar,Skipped,M).
 5826soldnf_solve(Goal,true,SkippedSoFar,[Goal|SkippedSoFar],M):-
 5827	skippable(Goal,M).
 5828
 5829soldnf_clause(Goal,_Body,M):-soldnf_builtin(Goal,M),!,fail.
 5830soldnf_clause(Goal,Body,M):-
 5831	clause(M:Goal,Body).
 5832
 5833soldnf_builtin(not(_Goal),_M):-!,fail.
 5834soldnf_builtin(A,M):-predicate_property(M:A,built_in).
 5835
 5836soldnfcall(Goal,true,M):-
 5837	M:Goal, !.
 5838soldnfcall(_,false,_M).
 5839
 5840conj_status(true,true,true):- !.
 5841conj_status(_,_,false).
 5842
 5843skippable(Pred,M):-
 5844	functor(Pred,Name,Arity),
 5845	M:'$aleph_global'(abducible,abducible(Name/Arity)).
 5846
 5847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 5848% L A Z Y  E V A L U A T I O N
 5849
 5850
 5851% lazy_evaluate_theory(+Clauses,+Lazy,+Pos,+Neg,-Theory)
 5852%       evaluate lazy preds in a set of clauses
 5853%	untested
 5854lazy_evaluate_theory([],_,_,_,[],_M).
 5855lazy_evaluate_theory([Refine|T],LazyPreds,Pos,Neg,[Refine1|T1],M):-
 5856	Refine = A-[B,C,D,Clause],
 5857        lazy_evaluate_refinement(D,Clause,LazyPreds,Pos,Neg,D1,Clause1,M),
 5858	Refine1 = A-[B,C,D1,Clause1],
 5859        lazy_evaluate_theory(T,LazyPreds,Pos,Neg,T1,M).
 5860
 5861% lazy evaluation of literals in a refinement operation
 5862lazy_evaluate_refinement([],Refine,Lazy,Pos,Neg,[],NewRefine,M):-
 5863	clause_to_list(Refine,Lits),
 5864	lazy_evaluate_refinement(Lits,Lazy,[],Pos,Neg,Lits1,M),
 5865	list_to_clause(Lits1,NewRefine), !.
 5866lazy_evaluate_refinement(Lits,_,Lazy,Pos,Neg,Lits1,NewRefine,M):-
 5867	Lits \= [],
 5868	lazy_evaluate_refinement(Lits,Lazy,[],Pos,Neg,Lits1,M),
 5869	get_pclause(Lits1,[],NewRefine,_,_,_,M), !.
 5870lazy_evaluate_refinement(Lits,Refine,_,_,_,Lits,Refine,_M).
 5871
 5872
 5873lazy_evaluate_refinement([],_,L,_,_,L,_M):- !.
 5874lazy_evaluate_refinement([Lit|Lits],LazyPreds,Path,PosCover,NegCover,Refine,M):-
 5875	lazy_evaluate([Lit],LazyPreds,Path,PosCover,NegCover,[Lit1],M), 
 5876	aleph_append([Lit1],Path,Path1), !,
 5877	lazy_evaluate_refinement(Lits,LazyPreds,Path1,PosCover,NegCover,Refine,M).
 5878
 5879
 5880% lazy evaluation of specified literals
 5881% all #'d arguments of these literals are evaluated at reduction-time
 5882% From Version 5 (dated Sat Nov 29 13:02:36 GMT 2003), collects both
 5883% input and output args (previously only collected input args)
 5884lazy_evaluate(Lits,[],_,_,_,Lits,_M):- !.
 5885lazy_evaluate([],_,_,_,_,[],_M):- !.
 5886lazy_evaluate([LitNum|LitNums],LazyPreds,Path,PosCover,NegCover,Lits,M):-
 5887	(integer(LitNum) ->
 5888		BottomExists = true,
 5889		M:'$aleph_sat_litinfo'(LitNum,Depth,Atom,I,O,D),
 5890		functor(Atom,Name,Arity),
 5891		aleph_member1(Name/Arity,LazyPreds), !,
 5892		get_pclause([LitNum|Path],[],(Lit:-(Goals)),_,_,_,M);
 5893		BottomExists = false,
 5894		Atom = LitNum,
 5895		Depth = 0,
 5896		functor(Atom,Name,Arity),
 5897		aleph_member1(Name/Arity,LazyPreds), !,
 5898		split_args(LitNum,_,I,O,C,M),
 5899		D = [],
 5900		list_to_clause([LitNum|Path],(Lit:-(Goals)))),
 5901	goals_to_clause(Goals,Clause),
 5902	lazy_prove(pos,Lit,Clause,PosCover,M),
 5903	(M:'$aleph_global'(positive_only,positive_only(Name/Arity))->
 5904		true;
 5905		lazy_prove_negs(Lit,Clause,NegCover,M)),
 5906	functor(LazyLiteral,Name,Arity),
 5907	collect_args(I,LazyLiteral,M),
 5908	collect_args(O,LazyLiteral,M),
 5909	lazy_evaluate1(BottomExists,Atom,Depth,I,O,C,D,LazyLiteral,NewLits,M),
 5910	retractall(M:'$aleph_local'(lazy_evaluate,_)),
 5911	lazy_evaluate(LitNums,LazyPreds,Path,PosCover,NegCover,NewLits1,M),
 5912	update_list(NewLits1,NewLits,Lits).
 5913lazy_evaluate([LitNum|LitNums],LazyPreds,Path,PosCover,NegCover,[LitNum|Lits],M):-
 5914	lazy_evaluate(LitNums,LazyPreds,Path,PosCover,NegCover,Lits,M).
 5915
 5916lazy_prove_negs(Lit,Clause,_,M):-
 5917	M:'$aleph_global'(lazy_negs,set(lazy_negs,true)), !,
 5918	M:'$aleph_global'(atoms,atoms(neg,NegCover)),
 5919	lazy_prove(neg,Lit,Clause,NegCover,M).
 5920lazy_prove_negs(Lit,Clause,NegCover,M):-
 5921	lazy_prove(neg,Lit,Clause,NegCover,M).
 5922
 5923collect_args([],_,_M).
 5924collect_args([Argno/_|Args],Literal,M):-
 5925	findall(Term,
 5926			(M:'$aleph_local'(lazy_evaluate,eval(pos,Lit)),
 5927			tparg(Argno,Lit,Term)),
 5928		PTerms),
 5929	findall(Term,
 5930			(M:'$aleph_local'(lazy_evaluate,eval(neg,Lit)),
 5931			tparg(Argno,Lit,Term)),
 5932		NTerms),
 5933	tparg(Argno,Literal,[PTerms,NTerms]),
 5934	collect_args(Args,Literal,M).
 5935
 5936% when construct_bottom = false
 5937% currently do not check if user's definition of lazily evaluated
 5938% literal corresponds to recall number in the modes
 5939lazy_evaluate1(false,Atom,_,I,O,C,_,Lit,NewLits,M):-
 5940	functor(Atom,Name,Arity),
 5941	p1_message('lazy evaluation'), p_message(Name),
 5942	functor(NewLit,Name,Arity),
 5943	findall(NewLit,(M:Lit,copy_args(Lit,NewLit,C)),NewLits),
 5944	copy_io_args(NewLits,Atom,I,O).
 5945
 5946lazy_evaluate1(true,Atom,Depth,I,O,_,D,Lit,NewLits,M):-
 5947	% M:'$aleph_sat'(lastlit,_),
 5948	call_library_pred(Atom,Depth,Lit,I,O,D,M),
 5949	findall(LitNum,(retract(M:'$aleph_local'(lazy_evaluated,LitNum))),NewLits).
 5950
 5951call_library_pred(OldLit,Depth,Lit,I,O,D,M):-
 5952	functor(OldLit,Name,Arity),
 5953	M:'$aleph_global'(lazy_recall,lazy_recall(Name/Arity,Recall)),
 5954	asserta(M:'$aleph_local'(callno,1)),
 5955	p1_message('lazy evaluation'), p_message(Name),
 5956	repeat,
 5957	evaluate(OldLit,Depth,Lit,I,O,D,M),
 5958	retract(M:'$aleph_local'(callno,CallNo)),
 5959	NextCall is CallNo + 1,
 5960	asserta(M:'$aleph_local'(callno,NextCall)),
 5961	NextCall > Recall,
 5962	!,
 5963	p_message('completed'),
 5964	retract(M:'$aleph_local'(callno,NextCall)).
 5965	 
 5966evaluate(OldLit,_,Lit,I,O,D,M):-
 5967	functor(OldLit,Name,Arity),
 5968	functor(NewLit,Name,Arity),
 5969	M:Lit,
 5970	copy_args(OldLit,NewLit,I),
 5971	copy_args(OldLit,NewLit,O),
 5972	copy_consts(Lit,NewLit,Arity),
 5973	update_lit(LitNum,false,NewLit,I,O,D,M),
 5974	\+(M:'$aleph_local'(lazy_evaluated,LitNum)),
 5975	asserta(M:'$aleph_local'(lazy_evaluated,LitNum)), !.
 5976evaluate(_,_,_,_,_,_,_M).
 5977
 5978copy_io_args([],_,_,_).
 5979copy_io_args([New|NewL],Old,I,O):-
 5980	copy_args(Old,New,I),
 5981	copy_args(Old,New,O),
 5982	copy_io_args(NewL,Old,I,O).
 5983
 5984copy_args(_,_,[]).
 5985copy_args(Old,New,[Arg/_|T]):-
 5986	tparg(Arg,Old,Term),
 5987	tparg(Arg,New,Term),
 5988	copy_args(Old,New,T), !.
 5989
 5990copy_consts(_,_,0):- !.
 5991copy_consts(Old,New,Arg):-
 5992	arg(Arg,Old,Term),
 5993	arg(Arg,New,Term1),
 5994	var(Term1), !,
 5995	Term1 = aleph_const(Term),
 5996	Arg0 is Arg - 1,
 5997	copy_consts(Old,New,Arg0).
 5998copy_consts(Old,New,Arg):-
 5999	Arg0 is Arg - 1,
 6000	copy_consts(Old,New,Arg0).
 6001
 6002% copy_modeterm(+Old,-New)
 6003%	copy term structure from Old to New
 6004%	by finding an appropriate mode declaration
 6005copy_modeterm(Lit1,Lit2,M):-
 6006	functor(Lit1,Name,Arity),
 6007	find_mode(mode,Name/Arity,Mode,M),
 6008	functor(Lit2,Name,Arity),
 6009	copy_modeterms(Mode,Lit2,Arity),
 6010	\+((\+ (Lit1 = Lit2))).
 6011
 6012% find_mode(+modetype,+Name/+Arity,-Mode)
 6013% find a mode for Name/Arity of type modetype
 6014find_mode(mode,Name/Arity,Mode,M):-
 6015	!,
 6016	functor(Mode,Name,Arity),
 6017	M:'$aleph_global'(mode,mode(_,Mode)).
 6018find_mode(modeh,Name/Arity,Mode,M):-
 6019	!,
 6020	functor(Mode,Name,Arity),
 6021	M:'$aleph_global'(modeh,modeh(_,Mode)).
 6022find_mode(modeb,Name/Arity,Mode,M):-
 6023	!,
 6024	functor(Mode,Name,Arity),
 6025	M:'$aleph_global'(modeb,modeb(_,Mode)).
 6026
 6027% copy_modeterms(+Mode,+Lit,+Arity)
 6028% 	copy all term structures in a mode template
 6029copy_modeterms(_,_,0):- !.
 6030copy_modeterms(Mode,Lit,Arg):-
 6031        arg(Arg,Mode,Term),
 6032	nonvar(Term),
 6033        functor(Term,Name,Arity),
 6034        \+((Name = '+'; Name = '-'; Name = '#')), !,
 6035        functor(NewTerm,Name,Arity),
 6036        arg(Arg,Lit,NewTerm),
 6037        copy_modeterms(Term,NewTerm,Arity),
 6038        Arg0 is Arg - 1,
 6039        copy_modeterms(Mode,Lit,Arg0).
 6040copy_modeterms(Mode,Lit,Arg):-
 6041        Arg0 is Arg - 1,
 6042        copy_modeterms(Mode,Lit,Arg0).
 6043
 6044
 6045% theorem-prover for lazy evaluation of literals
 6046lazy_prove(Type,Lit,Clause,Intervals,M):-
 6047        (Clause = (Head:-Body)->
 6048		lazy_prove(Intervals,Type,Lit,Head,Body,M);
 6049		lazy_prove(Intervals,Type,Lit,Clause,true,M)).
 6050
 6051lazy_prove([],_,_,_,_,_M).
 6052lazy_prove([Interval|Intervals],Type,Lit,Head,Body,M):-
 6053        lazy_index_prove(Interval,Type,Lit,Head,Body,M),
 6054        lazy_prove(Intervals,Type,Lit,Head,Body,M).
 6055
 6056lazy_index_prove(Start-Finish,_,_,_,_,_M):-
 6057        Start > Finish, !.
 6058lazy_index_prove(Start-Finish,Type,Lit,Head,Body,M):-
 6059        lazy_index_prove1(Type,Lit,Head,Body,Start,M),
 6060        Start1 is Start + 1,
 6061        lazy_index_prove(Start1-Finish,Type,Lit,Head,Body,M).
 6062
 6063% bind input args of lazy literal
 6064% each example gives an set of input bindings
 6065% this is different from Aleph 2 where only a single binding was obtained
 6066lazy_index_prove1(Type,Lit,Head,Body,Num,M):-
 6067        depth_bound_call((example(Num,Type,Head),Body),M),
 6068	\+(M:'$aleph_local'(lazy_evaluate,eval(Type,Lit))),
 6069        asserta(M:'$aleph_local'(lazy_evaluate,eval(Type,Lit))),
 6070        fail.
 6071lazy_index_prove1(_,_,_,_,_,_M).
 6072
 6073
 6074%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 6075% S L P
 6076% implemented as described by Muggleton, ILP-96
 6077
 6078condition_target(M):-
 6079	M:'$aleph_global'(condition,set(condition,true)),
 6080	add_generator(M),
 6081	M:'$aleph_global'(modeh,modeh(_,Pred)),
 6082	functor(Pred,Name,Arity),
 6083	p_message('conditioning'),
 6084	make_sname(Name,SName),
 6085	functor(SPred,SName,Arity),
 6086	SPred =.. [_|Args],
 6087	functor(Fact,Name,Arity),
 6088	M:example(_,_,Fact),
 6089	Fact =.. [_|Args], 
 6090	condition(SPred,M),
 6091	fail.
 6092condition_target(M):-
 6093	\+(M:'$aleph_global'(condition,set(condition,true))),
 6094	add_generator(M), !.
 6095condition_target(_M).
 6096
 6097
 6098add_generator(M):-
 6099	M:'$aleph_global'(modeh,modeh(_,Pred)),
 6100	functor(Pred,Name,Arity),
 6101	make_sname(Name,SName),
 6102	functor(SPred,SName,Arity),
 6103	(clause(M:SPred,_)-> 
 6104		true;
 6105		add_generator(Name/Arity,M),
 6106		p1_message('included generator'), p_message(SName/Arity)),
 6107	fail.
 6108add_generator(_M).
 6109
 6110add_generator(Name/Arity,M):-
 6111	make_sname(Name,SName),
 6112	functor(SPred,SName,Arity),
 6113	find_mode(modeh,Name/Arity,Mode,M),
 6114	once(copy_modeterms(Mode,SPred,Arity)),
 6115	split_args(Mode,Mode,Input,Output,Constants,M),
 6116	range_restrict(Input,SPred,[],B1),
 6117	range_restrict(Output,SPred,B1,B2),
 6118	range_restrict(Constants,SPred,B2,B3),
 6119	list_to_goals(B3,Body),
 6120	\+(clause(M:SPred,Body)),
 6121	asserta(M:(SPred:-Body)),
 6122	fail.
 6123add_generator(_,_M).
 6124
 6125make_sname(Name,SName):-
 6126	concat(['*',Name],SName).
 6127
 6128range_restrict([],_,R,R).
 6129range_restrict([Pos/Type|T],Pred,R0,R):-
 6130	functor(TCheck,Type,1),
 6131	tparg(Pos,Pred,X),
 6132	arg(1,TCheck,X),
 6133	range_restrict(T,Pred,[TCheck|R0],R).
 6134
 6135
 6136condition(Fact,M):-
 6137	slprove(condition,Fact,M), !.
 6138condition(_,_M).
 6139
 6140sample(_,0,[],_M):- !.
 6141sample(Name/Arity,N,S,M):-
 6142	functor(Pred,Name,Arity),
 6143	retractall(M:'$aleph_local'(slp_samplenum,_)),
 6144	retractall(M:'$aleph_local'(slp_sample,_)),
 6145	asserta(M:'$aleph_local'(slp_samplenum,1)),
 6146	repeat,
 6147	slprove(stochastic,Pred,M),
 6148	asserta(M:'$aleph_local'(slp_sample,Pred)),
 6149	retract(M:'$aleph_local'(slp_samplenum,N1)),
 6150	N2 is N1 + 1,
 6151	asserta(M:'$aleph_local'(slp_samplenum,N2)),
 6152	N2 > N,
 6153	!,
 6154	retract(M:'$aleph_local'(slp_samplenum,N2)),
 6155	functor(Fact,Name,Arity),
 6156	findall(Fact,(retract(M:'$aleph_local'(slp_sample,Fact))),S).
 6157
 6158gsample(Name/Arity,_,M):-
 6159        make_sname(Name,SName),
 6160        functor(SPred,SName,Arity),
 6161        clause(M:SPred,Body),
 6162        ground((SPred:-Body)), !,
 6163        update_gsample(Name/Arity,_,M).
 6164gsample(_,0,_M):- !.
 6165gsample(Name/Arity,N,M):-
 6166	functor(Pred,Name,Arity),
 6167	make_sname(Name,SName),
 6168	functor(SPred,SName,Arity),
 6169	Pred =.. [_|Args],
 6170	retractall(M:'$aleph_local'(slp_samplenum,_)),
 6171	asserta(M:'$aleph_local'(slp_samplenum,0)),
 6172	repeat,
 6173	slprove(stochastic,SPred,M),
 6174	SPred =..[_|Args],
 6175	retract(M:'$aleph_local'(slp_samplenum,N1)),
 6176	N2 is N1 + 1,
 6177	asserta(M:'$aleph_local'(slp_samplenum,N2)),
 6178	assertz(M:example(N2,rand,Pred)),
 6179	N2 >= N,
 6180	!,
 6181	retract(M:'$aleph_local'(slp_samplenum,N2)),
 6182	asserta(M:'$aleph_global'(size,size(rand,N))),
 6183	asserta(M:'$aleph_global'(last_example,last_example(rand,N))),
 6184	asserta(M:'$aleph_global'(atoms,atoms(rand,[1-N]))),
 6185	asserta(M:'$aleph_global'(atoms_left,atoms_left(rand,[1-N]))).
 6186
 6187update_gsample(Name/Arity,_,M):-
 6188        functor(Pred,Name,Arity),
 6189        make_sname(Name,SName),
 6190        functor(SPred,SName,Arity),
 6191        retractall(M:'$aleph_global'(gsample,gsample(_))),
 6192	retractall(M:'$aleph_local'(slp_samplenum,_)),
 6193        asserta(M:'$aleph_local'(slp_samplenum,0)),
 6194        SPred =.. [_|Args],
 6195        Pred =.. [_|Args],
 6196        clause(M:SPred,Body),
 6197        ground((SPred:-Body)),
 6198	record_example(check,rand,(Pred:-Body),N1,M),
 6199        retract(M:'$aleph_local'(slp_samplenum,_)),
 6200        asserta(M:'$aleph_local'(slp_samplenum,N1)),
 6201        fail.
 6202update_gsample(_,N,M):-
 6203        M:'$aleph_local'(slp_samplenum,N),
 6204        N > 0, !,
 6205        retract(M:'$aleph_local'(slp_samplenum,N)),
 6206        set(gsamplesize,N,M),
 6207        retract(M:'$aleph_global'(atoms,atoms(rand,_))),
 6208        retract(M:'$aleph_global'(atoms_left,atoms_left(rand,_))),
 6209        retract(M:'$aleph_global'(last_example,last_example(rand,_))),
 6210        assert(M:'$aleph_global'(atoms,atoms(rand,[1-N]))),
 6211        assert(M:'$aleph_global'(atoms_left,atoms_left(rand,[1-N]))),
 6212        assert(M:'$aleph_global'(last_example,last_example(rand,N))).
 6213update_gsample(_,_,_M).
 6214
 6215	
 6216slprove(_,true,_M):-
 6217	!.
 6218slprove(Mode,not(Goal),M):-
 6219	slprove(Mode,Goal,M),
 6220	!,
 6221	fail.
 6222slprove(Mode,(Goal1,Goal2),M):-
 6223	!,
 6224	slprove(Mode,Goal1,M),
 6225	slprove(Mode,Goal2,M).
 6226slprove(Mode,(Goal1;Goal2),M):-
 6227	!,
 6228	slprove(Mode,Goal1,M);
 6229	slprove(Mode,Goal2,M).
 6230slprove(_,Goal,_M):-
 6231	predicate_property(Goal,built_in), !,
 6232	Goal.
 6233slprove(stochastic,Goal,M):-
 6234	findall(Count/Clause,
 6235		(clause(M:Goal,Body),Clause=(Goal:-Body),find_count(Clause,Count,M)),
 6236		ClauseCounts),
 6237	renormalise(ClauseCounts,Normalised),
 6238	aleph_random(X),
 6239	rselect_clause(X,Normalised,(Goal:-Body)),
 6240	slprove(stochastic,Body,M).
 6241slprove(condition,Goal,M):-
 6242	functor(Goal,Name,Arity),
 6243	functor(Head,Name,Arity),
 6244	clause(M:Head,Body),
 6245	\+(\+((Head=Goal,slprove(condition,Body,M)))),
 6246	inc_count((Head:-Body),M).
 6247
 6248renormalise(ClauseCounts,Normalised):-
 6249	sum_counts(ClauseCounts,L),
 6250	L > 0,
 6251	renormalise(ClauseCounts,L,Normalised).
 6252
 6253sum_counts([],0).
 6254sum_counts([N/_|T],C):-
 6255	sum_counts(T,C1),
 6256	C is N + C1.
 6257
 6258renormalise([],_,[]).
 6259renormalise([Count/Clause|T],L,[Prob/Clause|T1]):-
 6260	Prob is Count/L,
 6261	renormalise(T,L,T1).
 6262
 6263rselect_clause(X,[P/C|_],C):- X =< P, !.
 6264rselect_clause(X,[P/_|T],C):-
 6265	X1 is X - P,
 6266	rselect_clause(X1,T,C).
 6267
 6268
 6269find_count(Clause,N,M):-
 6270	copy_term(Clause,Clause1),
 6271	M:'$aleph_global'(slp_count,Clause1,N), !.
 6272find_count(_,1,_M).
 6273	
 6274inc_count(Clause,M):-
 6275	retract(M:'$aleph_global'(slp_count,Clause,N)), !,
 6276	N1 is N + 1,
 6277	asserta(M:'$aleph_global'(slp_count,Clause,N1)).
 6278inc_count(Clause,M):-
 6279	asserta(M:'$aleph_global'(slp_count,Clause,2)).
 6280
 6281find_posgain(PCover,P,M):-
 6282	M:'$aleph_global'(greedy,set(greedy,true)), !,
 6283	interval_count(PCover,P).
 6284find_posgain(PCover,P,M):-
 6285	M:'$aleph_global'(atoms_left,atoms_left(pos,PLeft)),
 6286	intervals_intersection(PLeft,PCover,PC),
 6287	interval_count(PC,P).
 6288
 6289
 6290%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 6291% S E A R C H  I / O 
 6292
 6293record_clause(good,Label,Clause,_,M):-
 6294	setting(good,true,M), 
 6295	setting(goodfile_stream,Stream,M), !,
 6296	set_output(Stream),
 6297	Label = [_,_,L|_],
 6298	aleph_writeq('$aleph_good'(L,Label,Clause)),  write('.'), nl,
 6299	flush_output(Stream),
 6300	set_output(user_output).
 6301record_clause(Flag,Label,Clause,Nodes,M):-
 6302	Flag \= good,
 6303	setting(recordfile_stream,Stream,M), !,
 6304	set_output(Stream),
 6305	show_clause(Flag,Label,Clause,Nodes,M),
 6306	flush_output(Stream),
 6307	set_output(user_output).
 6308record_clause(_,_,_,_,_M).
 6309
 6310record_theory(Flag,Label,Clauses,Nodes,M):-
 6311	setting(recordfile_stream,Stream,M), !,
 6312        set_output(Stream),
 6313        show_theory(Label,Clauses,Nodes,Flag,M),
 6314	flush_output(Stream),
 6315        set_output(user_output).
 6316record_theory(_,_,_,_,_M).
 6317
 6318record_theory(Flag,Label,Clauses,Nodes,M):-
 6319	setting(recordfile_stream,Stream,M), !,
 6320        set_output(Stream),
 6321        show_theory(Label,Clauses,Nodes,Flag,M),
 6322	flush_output(Stream),
 6323        set_output(user_output).
 6324record_theory(_,_,_,_,_).
 6325
 6326record_sat_example(N,M):-
 6327	setting(recordfile_stream,Stream,M), !,
 6328	set_output(Stream),
 6329	p1_message('sat'), p_message(N),
 6330	flush_output(Stream),
 6331	set_output(user_output).
 6332record_sat_example(_,_M).
 6333
 6334record_search_stats(Clause,Nodes,Time,M):-
 6335	setting(recordfile_stream,Stream,M), !,
 6336	set_output(Stream),
 6337	p1_message('clauses constructed'), p_message(Nodes),
 6338	p1_message('search time'), p_message(Time),
 6339	p_message('best clause'),
 6340	pp_dclause(Clause,M),
 6341	% show(hypothesis),
 6342	flush_output(Stream),
 6343	set_output(user_output).
 6344record_search_stats(_,_,_,_M).
 6345
 6346record_tsearch_stats(Theory,Nodes,Time,M):-
 6347	setting(recordfile_stream,Stream,M), !,
 6348        set_output(Stream),
 6349        p1_message('theories constructed'), p_message(Nodes),
 6350        p1_message('search time'), p_message(Time),
 6351        p_message('best theory'),
 6352        pp_dclauses(Theory,M),
 6353        % show(hypothesis),
 6354	flush_output(Stream),
 6355        set_output(user_output).
 6356record_tsearch_stats(_,_,_,_).
 6357
 6358record_theory(Time,M):-
 6359	setting(recordfile_stream,Stream,M), !,
 6360        set_output(Stream),
 6361        show(theory,M),
 6362	p1_message('time taken'), p_message(Time),
 6363        nl,
 6364        (M:'$aleph_global'(maxcover,set(maxcover,true))->
 6365                show(theory/5,M), nl,
 6366                show(max_set/4,M), nl,
 6367                show(rules/1,M);
 6368                true),
 6369	flush_output(Stream),
 6370        set_output(user_output).
 6371record_theory(_,_M).
 6372
 6373record_features(Time,M):-
 6374	setting(recordfile_stream,Stream,M), !,
 6375        set_output(Stream),
 6376        show(features,M),
 6377	p1_message('time taken'), p_message(Time),
 6378	flush_output(Stream),
 6379        set_output(user_output).
 6380record_features(_,_).
 6381
 6382record_settings(M):-
 6383	setting(recordfile_stream,Stream,M), !,
 6384        set_output(Stream),
 6385	(M:'$aleph_global'(os,set(os,unix)) ->
 6386		execute(date),
 6387		execute(hostname);
 6388		true),
 6389	show(settings,M),
 6390	flush_output(Stream),
 6391        set_output(user_output).
 6392record_settings(_M).
 6393
 6394show_clause(Flag,Label,Clause,Nodes,M):-
 6395        broadcast(clause(Flag,Label,Clause,Nodes)), 
 6396	p_message('-------------------------------------'),
 6397	(Flag=good -> p_message('good clause');
 6398		(Flag=sample-> p_message('selected from sample');
 6399			p_message('found clause'))),
 6400	pp_dclause(Clause,M),
 6401	(setting(evalfn,Evalfn,M)-> true; Evalfn = coverage),
 6402	show_stats(Evalfn,Label),
 6403	p1_message('clause label'), p_message(Label),
 6404	p1_message('clauses constructed'), p_message(Nodes),
 6405	p_message('-------------------------------------').
 6406
 6407show_theory(Flag,Label,Clauses,Nodes,M):-
 6408        p_message('-------------------------------------'),
 6409        (Flag=good -> p_message('good theory');
 6410                (Flag=sample-> p_message('selected from sample');
 6411                        p_message('found theory'))),
 6412        pp_dclauses(Clauses,M),
 6413        (setting(evalfn,Evalfn,M)-> true; Evalfn = accuracy),
 6414        show_stats(Evalfn,Label),
 6415        p1_message('theory label'), p_message(Label),
 6416        p1_message('theories constructed'), p_message(Nodes),
 6417        p_message('-------------------------------------').
 6418
 6419update_search_stats(N,T,M):-
 6420	(retract(M:'$aleph_global'(search_stats,search_stats(N0,T0))) ->
 6421			N1 is N0 + N,
 6422			T1 is T0 + T;
 6423			N1 is N,
 6424			T1 is T),
 6425	asserta(M:'$aleph_global'(search_stats,search_stats(N1,T1))).
 6426
 6427record_total_stats(M):-
 6428	setting(recordfile_stream,Stream,M), !,
 6429	set_output(Stream),
 6430	show_total_stats(M),
 6431	flush_output(Stream),
 6432	set_output(user_output).
 6433record_total_stats(_M).
 6434
 6435record_atoms_left(M):-
 6436	setting(recordfile_stream,Stream,M), !,
 6437	set_output(Stream),
 6438	show_atoms_left(M),
 6439	flush_output(Stream),
 6440	set_output(user_output).
 6441record_atoms_left(_M).
 6442
 6443show_total_stats(M):-
 6444	M:'$aleph_global'(search_stats,search_stats(Nodes,_)), !,
 6445	p1_message('total clauses constructed'), p_message(Nodes).
 6446show_total_stats(_M).
 6447	
 6448show_atoms_left(M):-
 6449	M:'$aleph_global'(atoms_left,atoms_left(pos,PLeft)),
 6450	interval_count(PLeft,NLeft),
 6451	M:'$aleph_global'(size,size(pos,NPos)),
 6452	M:'$aleph_global'(search_stats,search_stats(_,Time)),
 6453	EstTime is (Time*NLeft)/(NPos - NLeft),
 6454	p1_message('positive examples left'), p_message(NLeft),
 6455	p1_message('estimated time to finish (secs)'), p_message(EstTime), !.
 6456show_atoms_left(_M).
 6457
 6458show_stats(Evalfn,[P,N,_,F|_]):-
 6459	((Evalfn = user; Evalfn = entropy; Evalfn = gini) ->
 6460		Value is -F;
 6461		Value is F
 6462	),
 6463	concat(['pos cover = ',P,' neg cover = ',N],Mess),
 6464	p1_message(Mess),
 6465	print_eval(Evalfn,Value).
 6466
 6467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 6468% A U T O  -- R E F I N E
 6469% 
 6470% built-in refinement operator
 6471
 6472gen_auto_refine(M):-
 6473	(setting(autorefine,true,M) -> true;
 6474		set(autorefine,true,M),
 6475		process_modes(M),
 6476		process_determs(M)),
 6477	!.
 6478gen_auto_refine(_M).
 6479
 6480
 6481process_modes(M):-
 6482	once(aleph_abolish('$aleph_link_vars'/2,M)),
 6483	once(aleph_abolish('$aleph_has_vars'/3,M)),
 6484	once(aleph_abolish('$aleph_has_ovar'/4,M)),
 6485	once(aleph_abolish('$aleph_has_ivar'/4,M)),
 6486	M:'$aleph_global'(modeb,modeb(_,Mode)),
 6487	process_mode(Mode,M),
 6488	fail.
 6489process_modes(M):-
 6490	M:'$aleph_global'(determination,determination(Name/Arity,_)),
 6491	find_mode(modeh,Name/Arity,Mode,M),
 6492	split_args(Mode,Mode,I,O,_,M),
 6493	functor(Lit,Name,Arity),
 6494	copy_modeterms(Mode,Lit,Arity),
 6495	add_ivars(Lit,I,M),
 6496	add_ovars(Lit,O,M),
 6497	add_vars(Lit,I,O,M),
 6498	fail.
 6499process_modes(_M).
 6500
 6501process_determs(M):-
 6502	once(aleph_abolish('$aleph_determination'/2,M)),
 6503	M:'$aleph_global'(determination,determination(Name/Arity,Name1/Arity1)),
 6504	functor(Pred,Name1,Arity1),
 6505	find_mode(modeb,Name1/Arity1,Mode,M),
 6506	copy_modeterms(Mode,Pred,Arity1),
 6507	Determ = M:'$aleph_determination'(Name/Arity,Pred),
 6508	(Determ -> true; assert(Determ)),
 6509	fail.
 6510process_determs(_M).
 6511
 6512process_mode(Mode,M):-
 6513	functor(Mode,Name,Arity),
 6514	split_args(Mode,Mode,I,O,C,M),
 6515	functor(Lit,Name,Arity),
 6516	copy_modeterms(Mode,Lit,Arity),
 6517	add_ioc_links(Lit,I,O,C,M),
 6518	add_ovars(Lit,O,M),
 6519	add_vars(Lit,I,O,M).
 6520
 6521add_ioc_links(Lit,I,O,C,M):-
 6522	Clause = ('$aleph_link_vars'(Lit,Lits):-
 6523			aleph:var_types(Lits,VT,M),
 6524			Body),
 6525	get_o_links(O,Lit,VT,true,OGoals,M),
 6526	get_i_links(I,Lit,VT,OGoals,IOGoals),
 6527	get_c_links(C,Lit,IOGoals,Body),
 6528	assert(M:Clause).
 6529
 6530add_ovars(Lit,O,M):-
 6531	aleph_member(Pos/Type,O),
 6532	tparg(Pos,Lit,V),
 6533	(M:'$aleph_has_ovar'(Lit,V,Type,Pos)->true;
 6534		assert(M:'$aleph_has_ovar'(Lit,V,Type,Pos))),
 6535	fail.
 6536add_ovars(_,_,_M).
 6537
 6538add_ivars(Lit,I,M):-
 6539	aleph_member(Pos/Type,I),
 6540	tparg(Pos,Lit,V),
 6541	(M:'$aleph_has_ivar'(Lit,V,Type,Pos)->true;
 6542		assert(M:'$aleph_has_ivar'(Lit,V,Type,Pos))),
 6543	fail.
 6544add_ivars(_,_,_M).
 6545
 6546add_vars(Lit,I,O,M):-
 6547        get_var_types(I,Lit,IVarTypes),
 6548        get_var_types(O,Lit,OVarTypes),
 6549        (M:'$aleph_has_vars'(Lit,IVarTypes,OVarTypes) -> true;
 6550        	assert(M:'$aleph_has_vars'(Lit,IVarTypes,OVarTypes))).
 6551
 6552get_var_types([],_,[]).
 6553get_var_types([Pos/Type|PlaceTypes],Lit,[Var/Type|Rest]):-
 6554        tparg(Pos,Lit,Var),
 6555        get_var_types(PlaceTypes,Lit,Rest).
 6556
 6557get_o_links([],_,_,Goals,Goals,_M).
 6558get_o_links([Pos/Type|T],Lit,VarTypes,GoalsSoFar,Goals,M):-
 6559	tparg(Pos,Lit,V),
 6560	Goal = (aleph:aleph_output_var(V,Type,VarTypes);
 6561		aleph:aleph_output_var(V,Type,Lit,Pos,M)),
 6562	prefix_lits((Goal),GoalsSoFar,G1),
 6563	get_o_links(T,Lit,VarTypes,G1,Goals,M).
 6564
 6565
 6566get_i_links([],_,_,Goals,Goals).
 6567get_i_links([Pos/Type|T],Lit,VarTypes,GoalsSoFar,Goals):-
 6568	tparg(Pos,Lit,V),
 6569	Goal = aleph:aleph_input_var(V,Type,VarTypes),
 6570	prefix_lits((Goal),GoalsSoFar,G1),
 6571	get_i_links(T,Lit,VarTypes,G1,Goals).
 6572
 6573get_c_links([],_,Goals,Goals).
 6574get_c_links([Pos/Type|T],Lit,GoalsSoFar,Goals):-
 6575	tparg(Pos,Lit,V),
 6576	TypeFact =.. [Type,C],
 6577	Goal = (TypeFact,V=C),
 6578	prefix_lits((Goal),GoalsSoFar,G1),
 6579	get_c_links(T,Lit,G1,Goals).
 6580	
 6581aleph_input_var(Var,Type,VarTypes):-
 6582        aleph_member(Var/Type1,VarTypes),
 6583	nonvar(Type1),
 6584	Type = Type1.
 6585
 6586aleph_output_var(Var,Type,VarTypes):-
 6587        aleph_member(Var/Type1,VarTypes),
 6588	nonvar(Type1),
 6589	Type = Type1.
 6590aleph_output_var(_,_,_).
 6591
 6592aleph_output_var(Var,Type,Lit,ThisPos,M):-
 6593	M:'$aleph_has_ovar'(Lit,Var,Type,Pos),
 6594	Pos @< ThisPos.
 var_types(+Atoms:list, -VarTypes:list, +Module:atomic) is det
Returns the types of variables in Atoms. Internal predicate. /
 6600var_types([Head|Body],VarTypes,M):-
 6601        hvar_types(Head,HVarTypes,M),
 6602        bvar_types(Body,HVarTypes,BVarTypes,M),
 6603        aleph_append(BVarTypes,HVarTypes,VarTypesList),
 6604        sort(VarTypesList,VarTypes).
 6605
 6606hvar_types(Head,HVarTypes,M):-
 6607	M:'$aleph_has_vars'(Head,IVarTypes,OVarTypes),
 6608        aleph_append(IVarTypes,OVarTypes,HVarTypes).
 6609
 6610bvar_types([],V,V,_M).
 6611bvar_types([Lit|Lits],VTSoFar,BVarTypes,M):-
 6612	M:'$aleph_has_vars'(Lit,IVarTypes,OVarTypes),!,
 6613        consistent_vartypes(IVarTypes,VTSoFar),
 6614        \+ inconsistent_vartypes(OVarTypes,VTSoFar),
 6615        aleph_append(OVarTypes,VTSoFar,VT1),
 6616        bvar_types(Lits,VT1,BVarTypes,M).
 6617bvar_types([not(Lit)|Lits],VTSoFar,BVarTypes,M):-
 6618	M:'$aleph_has_vars'(Lit,IVarTypes,OVarTypes),
 6619        consistent_vartypes(IVarTypes,VTSoFar),
 6620        \+ inconsistent_vartypes(OVarTypes,VTSoFar),
 6621        aleph_append(OVarTypes,VTSoFar,VT1),
 6622        bvar_types(Lits,VT1,BVarTypes,M).
 6623consistent_vartypes([],_).
 6624consistent_vartypes([Var/Type|VarTypes],VTSoFar):-
 6625        aleph_member2(Var/Type,VTSoFar),
 6626        consistent_vartypes(VarTypes,VTSoFar).
 6627                                                                                
 6628inconsistent_vartypes([Var/Type|_],VTSoFar):-
 6629        aleph_member(Var1/Type1,VTSoFar),
 6630        Var == Var1,
 6631        Type \== Type1, !.
 6632inconsistent_vartypes([_|VarTypes],VTSoFar):-
 6633        inconsistent_vartypes(VarTypes,VTSoFar).
 6634
 6635
 6636aleph_get_hlit(Name/Arity,Head,M):-
 6637	functor(Head,Name,Arity),
 6638	find_mode(modeh,Name/Arity,Mode,M),
 6639	once(split_args(Mode,Mode,_,_,C,M)),
 6640	copy_modeterms(Mode,Head,Arity),
 6641	get_c_links(C,Head,true,Equalities),
 6642	M:Equalities.
 6643
 6644aleph_get_lit(Lit,[H|Lits],M):-
 6645	functor(H,Name,Arity),
 6646	aleph_get_lit(Lit,Name/Arity,M),
 6647	M:'$aleph_link_vars'(Lit,[H|Lits]),
 6648	\+(aleph_member2(Lit,[H|Lits])).
 6649
 6650aleph_get_lit(Lit,Target,M):-
 6651	M:'$aleph_determination'(Target,Lit).
 6652
 6653% aleph_mode_linked(+Lits)
 6654% checks to see if a sequence of literals are within mode language
 6655% using information compiled by process_modes/0
 6656aleph_mode_linked([H|B],M):-
 6657	aleph_mode_linked(B,[H],M).
 6658
 6659aleph_mode_linked([],_,_M):- !.
 6660aleph_mode_linked([Lit|Lits],LitsSoFar,M):-
 6661	M:'$aleph_link_vars'(Lit,LitsSoFar),
 6662	aleph_append([Lit],LitsSoFar,L1),
 6663	aleph_mode_linked(Lits,L1,M).
 6664
 6665auto_refine(aleph_false,Head,M):-
 6666	example_saturated(Example,M), 
 6667	functor(Example,Name,Arity),
 6668        aleph_get_hlit(Name/Arity,Head,M),
 6669	Head \== aleph_false.
 6670auto_refine(aleph_false,Head,M):-
 6671        M:'$aleph_global'(modeh,modeh(_,Pred)),
 6672	functor(Pred,Name,Arity),
 6673        aleph_get_hlit(Name/Arity,Head,M),
 6674	Head \== aleph_false.
 6675auto_refine((H:-B),(H1:-B1),M):-
 6676        !,
 6677        goals_to_list((H,B),LitList),
 6678        setting(clauselength,L,M),
 6679        length(LitList,ClauseLength),
 6680        ClauseLength < L,
 6681        aleph_get_lit(Lit,LitList,M),
 6682        aleph_append([Lit],LitList,LitList1),
 6683        list_to_goals(LitList1,(H1,B1)),
 6684	\+(M:prune((H1:-B1))),
 6685	\+(tautology((H1:-B1),M)),
 6686	(setting(language,Lang,M) ->
 6687		lang_ok(Lang,H1,B1);
 6688		true),
 6689	(setting(newvars,NewVars,M) ->
 6690		newvars_ok(NewVars,H1,B1);
 6691		true).
 6692auto_refine(Head,Clause,M):-
 6693        auto_refine((Head:-true),Clause,M).
 6694
 6695% refinement with lookahead
 6696auto_refine(1,Clause1,Clause2,M):-
 6697	!,
 6698	auto_refine(Clause1,Clause2,M).
 6699auto_refine(L,Clause1,Clause2,M):-
 6700	L1 is L - 1, 
 6701	auto_refine(L1,Clause1,Clause,M),
 6702	(Clause2 = Clause;
 6703		auto_refine(Clause,Clause2,M)).
 6704
 6705auto_extend((H:-B),Lit,(H1:-B1),M):-
 6706        !,
 6707        goals_to_list((H,B),LitList),
 6708        setting(clauselength,L,M),
 6709        length(LitList,ClauseLength),
 6710        ClauseLength < L,
 6711        aleph_get_lit(Lit,LitList,M),
 6712        aleph_append([Lit],LitList,LitList1),
 6713        list_to_goals(LitList1,(H1,B1)),
 6714	(setting(language,Lang,M) ->
 6715		lang_ok(Lang,H1,B1);
 6716		true),
 6717	(setting(newvars,NewVars,M) ->
 6718		newvars_ok(NewVars,H1,B1);
 6719		true),
 6720	\+(tautology((H1:-B1),M)),
 6721	\+(M:prune((H1:-B1))).
 6722
 6723auto_extend((H),Lit,(H1:-B1),M):-
 6724        !,
 6725        goals_to_list(H,LitList),
 6726        setting(clauselength,L,M),
 6727        length(LitList,ClauseLength),
 6728        ClauseLength < L,
 6729        aleph_get_lit(Lit,LitList,M),
 6730        aleph_append([Lit],LitList,LitList1),
 6731        list_to_goals(LitList1,(H1,B1)),
 6732	(setting(language,Lang,M) ->
 6733		lang_ok(Lang,H1,B1);
 6734		true),
 6735	(setting(newvars,NewVars,M) ->
 6736		newvars_ok(NewVars,H1,B1);
 6737		true),
 6738	\+(tautology((H1:-B1),M)),
 6739	\+(M:prune((H1:-B1))).
 6740
 6741tautology((aleph_false:-Body),M):-
 6742	!,
 6743	in(Body,L1,Rest,M),
 6744	in(Rest,not(L2),M),
 6745	L1 == L2.
 6746tautology((Head:-Body),M):-
 6747	in(Body,Lit,M),
 6748	Head == Lit, !.
 6749
 6750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 6751% A U T O -- M O D E   
 6752
 6753% automatic inference of mode declarations given a set of
 6754% determinations. The procedure works in two parts: (i) finding
 6755% equivalence classes of types; and (ii) finding an input/output
 6756% assignment.
 6757% 
 6758% Finding equivalence classes of types is similar to
 6759% the work of McCreath and Sharma, Proc of the 8th Australian
 6760% Joint Conf on AI pages 75-82, 1995. However, unlike there
 6761% types in the same equivalence class are given the same name only if
 6762% they "overlap" significantly (the overlap of type1 with type2
 6763% is the proportion of elements of type1 that are also elements of type2). 
 6764% Significantly here means an overlap at least some threshold
 6765% T (set using typeoverlap, with default 0.95).
 6766% Since this may not be perfect, modes are also produced
 6767% for equality statements that re-introduce co-referencing amongst
 6768% differently named types in the same equivalence class.
 6769% The user has to however explicitly include a determination declaration for
 6770% the equality predicate.
 6771% 
 6772% The i/o assignment is not straightforward, as we may be dealing
 6773% with non-functional definitions. The assignment sought here is one
 6774% that maximises the number of input args as this gives the
 6775% largest bottom clause. This assignment is
 6776% is sought by means of a search procedure over mode sequences.
 6777% Suppose we have a mode sequence M = <m1,m2,..m{i-1}> that uses the types T.
 6778% An argument of type t in mode m{i} is an input iff t overlaps
 6779% significantly (used in the same sense as earlier) with some type in T.
 6780% Otherwise the argument is an output.
 6781% The utility of each mode sequence M is f(M) = g(M) + h(M) where
 6782% g(M) is the number of input args in M; and h(M) is a (lower) estimate
 6783% of the number of input args in any mode sequence of which M is a prefix.
 6784% The search strategy adopted is a simple hill-climbing one.
 6785%
 6786% All very complicated: there must be a simpler approach.
 6787% Requires generative background predicates.
 6788
 6789search_modes(M):-
 6790	M:'$aleph_global'(targetpred,targetpred(N/A)),
 6791	findall(N1/A1,determinations(N/A,N1/A1,M),L),
 6792	number_types([N/A|L],0,TypedPreds,Last),
 6793	get_type_elements(TypedPreds,M),
 6794	interval_to_list(1-Last,Types),
 6795	get_type_equivalences(Types,Equiv1,M),
 6796	merge_equivalence_classes(Equiv1,Equiv,M),
 6797	store_type_equivalences(Equiv,M),
 6798	setting(typeoverlap,Thresh,M),
 6799	infer_modes(TypedPreds,Thresh,Types,Modes,M),
 6800	infer_equalities(EqModes,M),
 6801	Modes = [_|BodyModes],
 6802	infer_negations(BodyModes,NegModes),
 6803	(setting(updateback,Update,M) -> true; Update = true),
 6804	p_message('found modes'),
 6805	add_inferred_modes(Modes,Update,M),
 6806	add_inferred_modes(EqModes,Update,M),
 6807	add_inferred_modes(NegModes,Update,M),
 6808	fail.
 6809search_modes(_M).
 6810
 6811number_types([],Last,[],Last).
 6812number_types([N/A|T],L0,[Pred|T1],L1):-
 6813	functor(Pred,N,A),
 6814	L is L0 + A,
 6815	number_types(A,L,Pred),
 6816	number_types(T,L,T1,L1).
 6817
 6818number_types(0,_,_):- !.
 6819number_types(A,N,Pred):-
 6820	arg(A,Pred,N),
 6821	A1 is A - 1,
 6822	N1 is N - 1,
 6823	number_types(A1,N1,Pred).
 6824
 6825get_type_elements([],_M).
 6826get_type_elements([Pred|Preds],M):-
 6827	functor(Pred,Name,Arity),
 6828	functor(Template,Name,Arity),
 6829	interval_to_list(1-Arity,AL),
 6830	get_type_elements(M:example(_,_,Template),Template,Pred,AL,M),
 6831	get_type_elements(Template,Template,Pred,AL,M),
 6832	get_type_elements(Preds,M).
 6833
 6834get_type_elements(Fact,Template,Pred,AL,M):-
 6835	aleph_member(Arg,AL),
 6836	findall(Val,(M:Fact,ground(Fact),arg(Arg,Template,Val)),Vals),
 6837	arg(Arg,Pred,Type),
 6838	sort(Vals,SVals),
 6839	(retract(M:'$aleph_search'(modes,type(Type,_,OtherVals))) ->
 6840		aleph_ord_union(SVals,OtherVals,ArgVals);
 6841		ArgVals = SVals),
 6842	length(ArgVals,N),
 6843	asserta(M:'$aleph_search'(modes,type(Type,N,ArgVals))),
 6844	fail.
 6845get_type_elements(_,_,_,_,_M).
 6846
 6847get_type_equivalences([],[],_M).
 6848get_type_equivalences([First|Rest],[Class|Classes],M):-
 6849	get_type_equivalence(Rest,[First],Class,Left,M),
 6850	get_type_equivalences(Left,Classes,M).
 6851
 6852get_type_equivalence([],Class1,Class,[],_):-
 6853	sort(Class1,Class).
 6854get_type_equivalence([Type|Rest],Class1,Class,Left,M):-
 6855	type_equivalent(Class1,Type,M), !,
 6856	get_type_equivalence(Rest,[Type|Class1],Class,Left,M).
 6857get_type_equivalence([Type|Rest],Class1,Class,[Type|Left],M):-
 6858	get_type_equivalence(Rest,Class1,Class,Left,M).
 6859
 6860merge_equivalence_classes([Class],[Class],_M):- !.
 6861merge_equivalence_classes(Classes1,Classes2,M):-
 6862        aleph_delete(Class1,Classes1,Left),
 6863        aleph_delete(Class2,Left,Left1),
 6864        class_equivalent(Class1,Class2,M), !,
 6865        aleph_ord_union(Class1,Class2,NewClass),
 6866        merge_equivalence_classes([NewClass|Left1],Classes2,M).
 6867merge_equivalence_classes(Classes,Classes,_M).
 6868
 6869class_equivalent(Class1,Class2,M):-
 6870        aleph_member(Type1,Class1),
 6871        type_equivalent(Class2,Type1,M), !.
 6872
 6873type_equivalent([T1|_],T2,M):-
 6874	M:'$aleph_search'(modes,type(T1,_,E1)),
 6875	M:'$aleph_search'(modes,type(T2,_,E2)),
 6876	intersects(E1,E2), !.
 6877type_equivalent([_|T],T2,M):-
 6878	type_equivalent(T,T2,M).
 6879
 6880store_type_equivalences([],_M).
 6881store_type_equivalences([[CType|Class]|Classes],M):-
 6882	length([CType|Class],N),
 6883	store_type_equivalence([CType|Class],CType,N,M),
 6884	store_type_equivalences(Classes,M).
 6885
 6886store_type_equivalence([],_,_,_M).
 6887store_type_equivalence([Type|Types],CType,Neq,M):-
 6888	retract(M:'$aleph_search'(modes,type(Type,N,Elements))),
 6889	store_type_overlaps(Types,Type,Elements,N,M),
 6890	asserta(M:'$aleph_search'(modes,type(Type,CType,Neq,N,Elements))),
 6891	store_type_equivalence(Types,CType,Neq,M).
 6892
 6893store_type_overlaps([],_,_,_,_M).
 6894store_type_overlaps([T1|Types],T,E,N,M):-
 6895	M:'$aleph_search'(modes,type(T1,N1,E1)),
 6896	aleph_ord_intersection(E1,E,Int),
 6897	length(Int,NInt),
 6898	O is NInt/N,
 6899	O1 is NInt/N1,
 6900	asserta(M:'$aleph_search'(modes,typeoverlap(T,T1,O,O1))),
 6901	store_type_overlaps(Types,T,E,N,M).
 6902
 6903infer_modes([Head|Rest],Thresh,Types,[Head1|Rest1],M):-
 6904	infer_mode(Head,Thresh,head,[],Head1,Seen,M),
 6905	aleph_delete_list(Seen,Types,TypesLeft),
 6906	infer_ordered_modes(Rest,Thresh,body,Seen,TypesLeft,Rest1,M).
 6907
 6908infer_ordered_modes([],_,_,_,_,[],_M):- !.
 6909infer_ordered_modes(L,Thresh,Loc,Seen,Left,[Mode|Rest],M):-
 6910	score_modes(L,Thresh,Seen,Left,ScoredPreds,M),
 6911	keysort(ScoredPreds,[_-Pred|_]), 
 6912	infer_mode(Pred,Thresh,Loc,Seen,Mode,Seen1,M),
 6913	aleph_delete(Pred,L,L1),
 6914	aleph_delete_list(Seen1,Left,Left1),
 6915	infer_ordered_modes(L1,Thresh,Loc,Seen1,Left1,Rest,M).
 6916
 6917score_modes([],_,_,_,[],_M).
 6918score_modes([Pred|Preds],Thresh,Seen,Left,[Cost-Pred|Rest],M):-
 6919	Pred =.. [_|Types],
 6920	evaluate_backward(Types,Thresh,Seen,G,M),
 6921	aleph_delete_list(Types,Left,Left1),
 6922	estimate_forward(Seen,Thresh,Left1,H0,M),
 6923	estimate_forward(Types,Thresh,Left1,H1,M),
 6924	Diff is H1 - H0,
 6925	(Diff < 0 -> H is 0; H is Diff),
 6926	Cost is -(G + H),
 6927	score_modes(Preds,Thresh,Seen,Left,Rest,M).
 6928
 6929evaluate_backward([],_,_,0.0,_M).
 6930evaluate_backward([Type|Types],Thresh,Seen,Score,M):-
 6931	best_overlap(Seen,Type,_,Overlap,M),
 6932	(Overlap >= Thresh -> Score1 = 1.0; Score1 = 0.0),
 6933	evaluate_backward(Types,Thresh,Seen,Score2,M),
 6934	Score is Score1 + Score2.
 6935
 6936estimate_forward([],_,_,0.0,_M).
 6937estimate_forward([Type|Types],Thresh,Left,Score,M):-
 6938        estimate_forward1(Left,Thresh,Type,S1,M),
 6939        estimate_forward(Types,Thresh,Left,S2,M),
 6940        Score is S1 + S2.
 6941
 6942estimate_forward1([],_,_,0.0,_M).
 6943estimate_forward1([T1|Types],Thresh,T,Score,M):-
 6944        type_overlap(T1,T,O1,M),
 6945	(O1 >= Thresh -> S1 is 1.0; S1 is 0.0),
 6946        estimate_forward1(Types,Thresh,T,S2,M),
 6947        Score is S1 + S2.
 6948
 6949infer_mode(Pred,Thresh,Loc,Seen0,InferredMode,Seen,M):-
 6950	Pred =.. [Name|Types],
 6951	infer_mode1(Types,Thresh,Loc,Seen0,Modes,M),
 6952	Mode =.. [Name|Modes],
 6953	length(Types,Arity),
 6954	(M:'$aleph_global'(targetpred,targetpred(Name/Arity)) ->
 6955		InferredMode = modeh(*,Mode);
 6956		InferredMode = mode(*,Mode)),
 6957	aleph_ord_union(Seen0,Types,Seen).
 6958
 6959infer_mode1([],_,_,_,[],_M).
 6960infer_mode1([Type|Types],Thresh,Loc,Seen,[Mode|Modes],M):-
 6961	best_overlap(Seen,Type,Best,Overlap,M),
 6962	(Overlap >= Thresh ->
 6963		M:'$aleph_search'(modes,typemapped(Best,_,NewType)),
 6964		asserta(M:'$aleph_search'(modes,typemapped(Type,Best,NewType))),
 6965		concat([type,NewType],Name),
 6966		Mode = +Name;
 6967		(Overlap > 0.0 ->
 6968			asserta(M:'$aleph_search'(modes,typemapped(Type,Best,Type)));
 6969			asserta(M:'$aleph_search'(modes,typemapped(Type,Type,Type)))),
 6970		concat([type,Type],Name),
 6971		(Loc = head -> Mode = +Name; Mode = -Name)
 6972	),
 6973	infer_mode1(Types,Thresh,Loc,Seen,Modes,M).
 6974
 6975
 6976best_overlap([T1],T,T1,O,M):-
 6977	!,
 6978	type_overlap(T,T1,O,M).
 6979best_overlap([T1|Types],T,Best,O,M):-
 6980	type_overlap(T,T1,O1,M),
 6981	best_overlap(Types,T,T2,O2,M),
 6982	(O2 > O1 -> O is O2, Best = T2; O is O1, Best = T1).
 6983best_overlap([],T,T,0.0,_M).
 6984
 6985type_overlap(T,T1,O,M):-
 6986	T > T1, !,
 6987	(M:'$aleph_search'(modes,typeoverlap(T1,T,_,O)) -> true; O = 0.0).
 6988type_overlap(T,T1,O,M):-
 6989	(M:'$aleph_search'(modes,typeoverlap(T,T1,O,_)) -> true; O = 0.0).
 6990
 6991
 6992infer_equalities(EqModes,M):-
 6993	findall(mode(1,(Eq)),(pairwise_equality(Eq,M);grounding_equality(Eq,M)),
 6994		EqL),
 6995	sort(EqL,EqModes).
 6996
 6997infer_negations([],[]).
 6998infer_negations([mode(_,Pred)|Modes],NegModes):-
 6999	Pred =.. [_|Args],
 7000	aleph_member1(-_,Args), !,
 7001	infer_negations(Modes,NegModes).
 7002infer_negations([mode(_,Pred)|Modes],[mode(1,not(Pred))|NegModes]):-
 7003	infer_negations(Modes,NegModes).
 7004	
 7005
 7006pairwise_equality((+N1 = +N2),M):-
 7007	M:'$aleph_search'(modes,typemapped(_,Best,T1)),
 7008	M:'$aleph_search'(modes,typemapped(Best,_,T2)),
 7009	T1 \== T2,
 7010	concat([type,T1],N1),
 7011	concat([type,T2],N2).
 7012grounding_equality((+N1 = #N1),M):-
 7013	M:'$aleph_search'(modes,typemapped(T1,_,T1)),
 7014	concat([type,T1],N1).
 7015
 7016add_inferred_modes([],_,_M).
 7017add_inferred_modes([Mode|Modes],Flag,M):-
 7018	write(Mode), nl,
 7019	(Flag = true -> M:Mode; true),
 7020	add_inferred_modes(Modes,Flag,M).
 7021	
 7022
 7023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 7024% S T O C H A S T I C   S E A R C H
 7025 
 7026% sample_clauses(+N,-Clauses)
 7027%	return sample of at most N legal clauses from hypothesis space
 7028%	If a bottom clause exists then
 7029%		Each clause is drawn randomly. The length of the clause is
 7030%		determined by:
 7031%			(a) user-specified distribution over clauselengths
 7032%			    using set(clauselength_distribution,Distribution);
 7033%			    Distribution is a list of the form p1-1, p2-2,...
 7034%			    specifying that clauselength 1 has prob p1, etc.
 7035%			    Note: sum pi must = 1. This is not checked; or
 7036%			(b) uniform distribution over all legal clauses.
 7037%			    (if clauselength_distribution is not set)
 7038%			    this uses a Monte-Carlo estimate of the number of
 7039%			    legal clauses in the hypothesis space
 7040%	If a bottom clause does not exist, then legal clauses are constructed
 7041%	using the mode declarations. Only option (a) is allowed. If
 7042%	clauselength_distribution is not set, then a uniform distribution over
 7043%	lengths is assumed.
 7044%	Each element of Clauses is of the form L-[E,T,Lits,Clause] where
 7045%	L is the clauselength; E,T are example number and type (pos, neg) used
 7046%	to build the bottom clause; Lits contains the literal numbers in the
 7047%	bottom clause for Clause. If no bottom clause then E,T = 0 and Lits = []
 7048% 	Clauses is in ascending order of clause length
 7049sample_clauses(N,Clauses,M):-
 7050	setting(construct_bottom,Bottom,M),
 7051	sample_nclauses(Bottom,N,Clauses,M).
 7052
 7053sample_nclauses(false,N,Clauses,M):-
 7054	!,
 7055	gen_auto_refine(M),
 7056	(setting(clauselength_distribution,D,M) -> true;
 7057		setting(clauselength,CL,M),
 7058		Uniform is 1.0/CL,
 7059		distrib(1-CL,Uniform,D)),
 7060	sample_nclauses_using_modes(N,D,CList,M),
 7061	remove_alpha_variants(CList,CList1),
 7062	keysort(CList1,Clauses).
 7063sample_nclauses(_,N,Clauses,M):-
 7064	retractall(M:'$aleph_sat'(random,rselect(_))),
 7065	(M:'$aleph_sat'(example,example(_,_)) -> true; rsat(M)),
 7066	setting(clauselength,CL,M),
 7067	(setting(clauselength_distribution,Universe,M) ->
 7068		Sample is N;
 7069		estimate_numbers(CL,1,400,Universe,M),
 7070		(N > Universe -> Sample is Universe; Sample is N)),
 7071	get_clause_sample(Sample,Universe,CL,CList,M),
 7072	keysort(CList,Clauses).
 7073
 7074% sample_nclauses_using_modes(+N,+D,-Clauses)
 7075% 	get upto N legal clauses using mode declarations
 7076%	and distribution D over clauselengths
 7077
 7078sample_nclauses_using_modes(0,_,[],_M):- !.
 7079sample_nclauses_using_modes(N,D,[Clause|Rest],M):-
 7080	legal_clause_using_modes(100,D,Clause,M),
 7081	N1 is N - 1,
 7082	sample_nclauses_using_modes(N1,D,Rest,M).
 7083
 7084% legal_clause_using_modes(+N,+D,-Clause,M)
 7085%	make at most N attempts to obtain a legal clause Clause
 7086%	from mode language using distribution D over clauselengths
 7087%	if all N attempts fail, then just return most general clause
 7088legal_clause_using_modes(N,D,L-[0,0,[],Clause],M):-
 7089	N > 0,
 7090	sample_clause_using_modes(D,L,Clause,M),
 7091	\+(M:prune(Clause)),
 7092	split_clause(Clause,Head,Body),
 7093	(setting(language,Lang,M) ->
 7094        	lang_ok(Lang,Head,Body);
 7095		true),
 7096	(setting(newvars,NewVars,M) ->
 7097		newvars_ok(NewVars,Head,Body);
 7098		true),
 7099	!.
 7100legal_clause_using_modes(N,D,Clause,M):-
 7101	N > 1,
 7102	N1 is N - 1,
 7103	legal_clause_using_modes(N1,D,Clause,M), !.
 7104legal_clause_using_modes(_,_,1-[0,0,[],Clause],M):-
 7105	sample_clause_using_modes([1.0-1],1,Clause,M).
 7106
 7107sample_clause_using_modes(D,L,Clause,M):-
 7108	findall(H,auto_refine(aleph_false,H,M),HL),
 7109	HL \= [],
 7110	random_select(Head,HL,_),
 7111	draw_element(D,L),
 7112	(L = 1 -> Clause = Head;
 7113		L1 is L - 1,
 7114		sample_clause_using_modes(L1,Head,Clause,M)).
 7115
 7116sample_clause_using_modes(N,ClauseSoFar,Clause,M):-
 7117	findall(C,auto_refine(ClauseSoFar,C,M),CL),
 7118	CL \= [], !,
 7119	(N = 1 -> random_select(Clause,CL,_);
 7120		random_select(C1,CL,_),
 7121		N1 is N - 1,
 7122		sample_clause_using_modes(N1,C1,Clause,M)).
 7123sample_clause_using_modes(_,Clause,Clause,_M).
 7124
 7125
 7126% get_clause_sample(+N,+U,+CL,-Clauses,M)
 7127% 	get upto N legal clauses of at most length CL drawn from universe U
 7128%	U is either the total number of legal clauses
 7129%		or a distribution over clauselengths
 7130%	the clauses are constructed by drawing randomly from bottom
 7131get_clause_sample(0,_,_,[],_):- !.
 7132get_clause_sample(N,Universe,CL,[L-[E,T,C1,C]|Clauses],M):-
 7133        (number(Universe) ->
 7134		get_rrandom(Universe,ClauseNum),
 7135		num_to_length(ClauseNum,CL,L,M),
 7136		UpperLim is CL;
 7137		draw_element(Universe,L),
 7138		UpperLim is L),
 7139	draw_legalclause_wo_repl(L,UpperLim,C,C1,M), !,
 7140	M:'$aleph_sat'(example,example(E,T)),
 7141	N1 is N - 1,
 7142	get_clause_sample(N1,Universe,CL,Clauses,M).
 7143get_clause_sample(N,Universe,CL,Clauses,M):-
 7144	N1 is N - 1,
 7145	get_clause_sample(N1,Universe,CL,Clauses,M).
 7146
 7147% draw_legalclause_wo_repl(+L,+CL,-C,-Lits,M)
 7148%	randomly draw without replacement a legal clause of length >= L and =< CL 
 7149%	also returns literals from bottom used to construct clause
 7150draw_legalclause_wo_repl(L,CL,C,C1,M):-
 7151	L =< CL,
 7152	randclause_wo_repl(L,C,legal,C1,M), !.
 7153draw_legalclause_wo_repl(L,CL,C,C1,M):-
 7154	L < CL,
 7155	L1 is L + 1,
 7156	draw_legalclause_wo_repl(L1, CL,C,C1,M).
 7157
 7158% estimate_clauselength_distribution(+L,+T,+K,-D,M)
 7159%	for each clauselength l <= L, estimate the probability of
 7160%	drawing a good clause
 7161%	here, a ``good clause'' is one that is in the top K-percentile of clauses
 7162%	estimation is by Monte Carlo using at most T trials
 7163%	probabilities are normalised to add to 1
 7164estimate_clauselength_distribution(L,T,K,D,M):-	
 7165	M:'$aleph_sat'(example,example(Type,Example)),
 7166	M:'$aleph_sat'(random,clauselength_distribution(Type,Example,L,T,K,D)), !.
 7167estimate_clauselength_distribution(L,T,K,D,M):-	
 7168	setting(evalfn,Evalfn,M),
 7169	estimate_clauselength_scores(L,T,Evalfn,[],S,M),
 7170	select_good_clauses(S,K,Good),
 7171	estimate_frequency(L,Good,Freq),
 7172	normalise_distribution(Freq,D),
 7173	(M:'$aleph_sat'(example,example(Type,Example)) ->
 7174		asserta(M:'$aleph_sat'(random,clauselength_distribution(Type,
 7175						Example,L,T,K,D)));
 7176		true).
 7177
 7178estimate_clauselength_scores(0,_,_,S,S,_):- !.
 7179estimate_clauselength_scores(L,T,Evalfn,S1,S,M):-
 7180	set(clauselength_distribution,[1.0-L],M),
 7181	p1_message('Estimate scores of clauses with length'), p_message(L),
 7182	sample_clauses(T,Clauses,M),
 7183	estimate_scores(Clauses,Evalfn,S1,S2,M),
 7184	L1 is L - 1,
 7185	estimate_clauselength_scores(L1,T,Evalfn,S2,S,M).
 7186
 7187estimate_scores([],_,S,S,_M):- !.
 7188estimate_scores([L-[_,_,_,C]|Rest],Evalfn,S1,S,M):-
 7189	label_create(C,Label,M),
 7190	extract_count(pos,Label,PC),
 7191	extract_count(neg,Label,NC),
 7192	complete_label(Evalfn,C,[PC,NC,L],[_,_,_,Val|_],M),
 7193	estimate_scores(Rest,Evalfn,[-Val-L|S1],S,M).
 7194	
 7195% ``good'' clauses are defined to be those in the top K-percentile
 7196%	policy on ties is to include them
 7197select_good_clauses(S,K,Good):-
 7198	keysort(S,S1),
 7199	length(S1,Total),
 7200	N is integer(K*Total/100),
 7201	select_good_clauses(S1,N,[],Good).
 7202
 7203select_good_clauses([],_,Good,Good):- !.
 7204select_good_clauses(_,N,Good,Good):- N =< 0, !.
 7205select_good_clauses([Score-X|T],N,GoodSoFar,Good):-
 7206	select_good_clauses(T,Score,N,[Score-X|GoodSoFar],N0,Good1,T1),
 7207	N1 is N0 - 1,
 7208	select_good_clauses(T1,N1,Good1,Good).
 7209
 7210select_good_clauses([],_,N,G,N,G,[]):- !.
 7211select_good_clauses([Score-X|T],Score,N,GoodSoFar,N0,Good1,T1):-
 7212	!,
 7213	N1 is N - 1,
 7214	select_good_clauses(T,Score,N1,[Score-X|GoodSoFar],N0,Good1,T1).
 7215select_good_clauses(L,_,N,G,N,G,L).
 7216
 7217estimate_frequency(0,_,[]).
 7218estimate_frequency(L,Good,[N-L|T]):-
 7219	count_frequency(Good,L,N),
 7220	L1 is L - 1,
 7221	estimate_frequency(L1,Good,T).
 7222
 7223count_frequency([],_,0).
 7224count_frequency([Entry|T],X,N):-
 7225	count_frequency(T,X,N1),
 7226	(Entry = _-X -> N is N1 + 1; N is N1).
 7227
 7228% 	estimate total number of legal clauses in space
 7229%	bounded by bot
 7230estimate_numbers(Total,M):- 
 7231	(M:'$aleph_sat'(example,example(_,_)) -> true; rsat),
 7232	setting(clauselength,CL,M),
 7233	estimate_numbers(CL,1,400,Total,M).
 7234
 7235% estimate_numbers(+L,+Trials,+Sample,-T,M)
 7236% 	estimate total number of legal clauses of length <= L in space
 7237%	bounded by bot
 7238%	estimated number is cached for future use
 7239%	estimation is by Monte Carlo, averaged over Trials trials
 7240%	with given sample size
 7241estimate_numbers(L,Trials,Sample,Total,M):-
 7242	M:'$aleph_sat'(example,example(Type,Example)),
 7243	M:'$aleph_sat'(random,sample(Type,Example,L,Trials,Sample)),
 7244	M:'$aleph_sat'(random,hypothesis_space(Total)), !.
 7245estimate_numbers(L,Trials,Sample,Total,M):-
 7246	retractall(M:'$aleph_sat'(random,sample(_,_,_,_,_))),
 7247	retractall(M:'$aleph_sat'(random,hypothesis_space(_))),
 7248	estimate_numbers(L,Trials,Sample,0,Total,M),
 7249	asserta(M:'$aleph_sat'(random,hypothesis_space(Total))),
 7250	M:'$aleph_sat'(example,example(Type,Example)),
 7251	asserta(M:'$aleph_sat'(random,sample(Type,Example,L,Trials,Sample))).
 7252
 7253% estimate_numbers(+L,+Trials,+Sample,+TotalSoFar,-Total)
 7254%	estimate the number of legal clauses of length <= L
 7255%	estimated number of legal clauses at each length are cached for future use
 7256%	TotalSoFar is an accumulator of the number legal clauses so far
 7257%	Total is the cumulative total of the number of legal clauses
 7258estimate_numbers(0,_,_,T,T,_M):- !.
 7259estimate_numbers(L,Trials,Sample,TotalSoFar,T,M):-
 7260	retractall(M:'$aleph_sat'(random,number_of_clauses(L,_))),
 7261	estimate_number(Trials,Sample,L,T0,M),
 7262	asserta(M:'$aleph_sat'(random,number_of_clauses(L,T0))),
 7263	L1 is L - 1,
 7264	T1 is T0 + TotalSoFar,
 7265	estimate_numbers(L1,Trials,Sample,T1,T,M).
 7266
 7267% estimate_number(+T,+S,+L,-N,M)
 7268%	monte carlo estimate of number of legal clauses of length L
 7269%	estimate formed from average over T trials with sample S
 7270estimate_number(_,_,L,0,M):-
 7271        M:'$aleph_sat'(lastlit,Last),
 7272        Last < L, !.   
 7273estimate_number(T,S,L,N,M):-
 7274	T > 0,
 7275	p1_message('Estimate legal clauses with length'), p_message(L),
 7276	estimate_number(T,S,0,L,Total,M),
 7277	N is float(Total/T),
 7278	concat(['trials=',T,' sample=', S, ' estimate=', N],Mess),
 7279	p_message(Mess).
 7280
 7281estimate_number(1,S,Total,L,N,M):-
 7282	!,
 7283	estimate_number(L,S,N1,M),
 7284	N is Total + N1.
 7285estimate_number(T,S,Total,L,N,M):-
 7286	p_message('New Trial'),
 7287	estimate_number(L,S,N1,M),
 7288	Total1 is Total + N1,
 7289	T1 is T - 1,
 7290	estimate_number(T1,S,Total1,L,N,M).
 7291
 7292% estimate_number(+L,+S,-N)
 7293%	estimate the number of legal clauses of length L in the search space
 7294%	estimation based on sample size S
 7295estimate_number(1,_,1,_M):- !.
 7296estimate_number(L,S,N,M):-
 7297	estimate_proportion(S,L,legal,P,_,M),
 7298	M:'$aleph_sat'(lastlit,Last),
 7299	total_clauses(L,Last,Total),
 7300	N is float(P*Total).
 7301
 7302% estimate_proportion(+N,+L,+S,-P,-Clauses,M)
 7303%	estimate prop. of at most N random clauses of length L and status S
 7304%	clauses are generated without replacement
 7305%	S is one of legal or illegal depending on whether C is inside or
 7306%		outside the mode language provided
 7307%	Clauses is the list of at most N def. clauses
 7308%	If S is a variable then clauses can be legal or illegal
 7309%	Thus estimate_proportion(10000,2,S,P,C,M) returns the
 7310%		proportion and list of 2 literal clauses which are either
 7311%		legal or illegal in a sample of at most 10000
 7312%	Keeps legal clauses obtained in rselect_legal for later use
 7313estimate_proportion(0,_,_,0,[],_M):- !.
 7314estimate_proportion(N,L,S,P,Clauses,M):-
 7315	retractall(M:'$aleph_sat'(random,rselect(_))),
 7316	retractall(M:'$aleph_sat'(random,rselect_legal(L,_,_,_,_))),
 7317	get_random_wo_repl(N,L,Clauses,M),
 7318	length(Clauses,Total),
 7319	count_clause_status(Clauses,S,A,_),
 7320	(Total = 0 -> P = 0; P is A/Total),
 7321	M:'$aleph_sat'(example,example(E,T)),
 7322	retractall(M:'$aleph_sat'(random,rselect(_))),
 7323	store_legal_clauses(Clauses,L,E,T,M).
 7324
 7325% get_random_wo_repl(+N,+L,-List,M)
 7326%	randomly construct at most N definite clauses of length L
 7327%	returns Status/Clause list where Status is one of legal/illegal
 7328get_random_wo_repl(0,_,[],_,_M):- !.
 7329get_random_wo_repl(N,L,[S/[C,C1]|Clauses],M):-
 7330	randclause_wo_repl(L,C,S,C1,M), !,
 7331	N1 is N - 1,
 7332	get_random_wo_repl(N1,L,Clauses,M).
 7333get_random_wo_repl(_,_,[],_M).
 7334
 7335% print_distribution
 7336print_distribution(M):-
 7337	write('Clause Length'), tab(8), write('Estimated number of clauses'), nl,
 7338	write('_____________'), tab(8), write('___________________________'), nl,
 7339	findall(L-N,M:'$aleph_sat'(random,number_of_clauses(L,N)),List),
 7340	sort(List,List1),
 7341	aleph_member(L-N,List1),
 7342	write(L), tab(20), write(N), nl,
 7343	fail.
 7344print_distribution(M):-
 7345	nl,
 7346	write('Estimated size of hypothesis space = '),
 7347	(M:'$aleph_sat'(random,hypothesis_space(S)) -> true; S = 0),
 7348	write(S), write(' clauses'), nl.
 7349	
 7350% count_clause_status(+List,+Status,-C1,-C2)
 7351%	count number of clauses in List with status Status
 7352%	C1 is the number of such clauses
 7353%	C2 is the number of clauses with some other status
 7354count_clause_status(_,S,_,0):-
 7355	var(S), !.
 7356count_clause_status(Clauses,S,A,B):-
 7357	count_clause_status1(Clauses,S,A,B).
 7358
 7359count_clause_status1([],_,0,0):- !.
 7360count_clause_status1([S1/_|T],S,A,B):-
 7361	count_clause_status1(T,S,A1,B1),
 7362	(S == S1 -> A is A1 + 1, B is B1; A is A1, B is B1 + 1).
 7363
 7364% store_legal_clauses(+List,+L,+E,+T)
 7365% store all legal clauses of length L obtained with bottom clause for
 7366% example E of type T
 7367% useful later when a random legal clause of length L is required
 7368store_legal_clauses([],_,_,_,_M).
 7369store_legal_clauses([S/[C,C1]|Clauses],L,E,T,M):-
 7370	(S == legal ->
 7371		asserta(M:'$aleph_sat'(random,rselect_legal(L,E,T,C,C1)));
 7372		true),
 7373	store_legal_clauses(Clauses,L,E,T,M).
 7374
 7375% randclause_wo_repl(+L,-C,-S,-Lits)
 7376% as randclause/4 but ensures that clause obtained is without replacement
 7377%	only makes at most 100 attempts to find such a clause
 7378%	also returns lits from bottom clause selected
 7379%	if all attempts fail, then return the most general clause
 7380randclause_wo_repl(L,C,S,C1,M):-
 7381	randclause_wo_repl(100,L,C,S,C1,M).
 7382
 7383randclause_wo_repl(N,L,C,S,C1,M):-
 7384	N > 0,
 7385	randclause(L,C,S,C1,M),	% if not accounting for variable renamings
 7386	% copy_term(C,C1),	% if accounting for variable renamings	
 7387	% numbervars(C1,0,_),	% if accounting for variable renamings
 7388	\+(M:prune(C)),
 7389	split_clause(C,Head,Body),
 7390	(setting(language,Lang,M) ->
 7391		lang_ok(Lang,Head,Body);
 7392		true),
 7393	(setting(newvars,NewVars,M) ->
 7394		newvars_ok(NewVars,Head,Body);
 7395		true),
 7396	\+(M:'$aleph_sat'(random,rselect(C1))), !,
 7397	asserta(M:'$aleph_sat'(random,rselect(C1))).
 7398randclause_wo_repl(N,L,C,S,C1,M):-
 7399	N > 0,
 7400	N1 is N - 1,
 7401	randclause_wo_repl(N1,L,C,S,C1,M), !.
 7402randclause_wo_repl(_,1,C,S,C1,M):-
 7403	randclause(1,C,S,C1,M).	% if not accounting for variable renamings
 7404	% copy_term(C,C1),	% if accounting for variable renamings	
 7405	% numbervars(C1,0,_),	% if accounting for variable renamings
 7406
 7407% randclause(+L,-C,-S,-Lits,M)
 7408%	returns definite clause C of length L with status S comprised of Lits
 7409%	drawn at random from the bottom clause
 7410%	also returns the literals in the bottom clause that were selected
 7411%	body literals of C are randomly selected from the bottom clause
 7412%	S is one of legal or illegal depending on whether C is inside or
 7413%		outside the mode language provided
 7414% needs a bottom clause to be constructed before it is meaningful
 7415% this can be done with the sat predicate for eg: sat(1)
 7416% if set(store_bottom,true) then use stored bottom clause instead
 7417% if S is legal, then checks to see if previously generated legal
 7418% clauses exist for this bottom clause (these would have been generated
 7419% when trying to estimate the number of legal clause at each length)
 7420randclause(1,C,legal,[1],M):-
 7421	!,
 7422	bottom_key(_,_,Key,_,M),
 7423        (Key = false ->
 7424		get_pclause([1],[],C,_,_,_,M);
 7425		get_pclause([1],Key,[],C,_,_,_,M)).
 7426randclause(L,C,Status,Lits,M):-
 7427	Status == legal,
 7428	M:'$aleph_sat'(example,example(E,T)),
 7429	retract(M:'$aleph_sat'(random,rselect_legal(L,E,T,C,Lits))).
 7430% can do things more efficiently if we want to generate legal clauses only
 7431randclause(L,C,Status,Lits,M):-
 7432	Status == legal, !,
 7433	bottom_key(_,_,Key,_,M),
 7434        (Key = false ->
 7435        	M:'$aleph_sat_litinfo'(1,_,_,_,_,D);
 7436		M:'$aleph_sat_litinfo'(1,Key,_,_,_,_,D)),
 7437        L1 is L - 1,
 7438        repeat,
 7439        randselect1(L1,Key,D,[1],BodyLits,M),
 7440        Lits = [1|BodyLits],
 7441	clause_status(Lits,Key,[],legal,legal,M), !,
 7442        (Key = false ->
 7443        	get_pclause(Lits,[],C,_,_,_,M);
 7444        	get_pclause(Lits,Key,[],C,_,_,_,M)).
 7445randclause(L,C,Status,Lits,M):-
 7446	L1 is L - 1,
 7447	bottom_key(_,_,Key,_,M),
 7448	(Key = false ->
 7449		M:'$aleph_sat'(lastlit,Last);
 7450		M:'$aleph_sat'(lastlit,Key,Last)),
 7451	repeat,
 7452	randselect(L1,Last,Key,[],BodyLits,M),
 7453	aleph_append(BodyLits,[1],Lits),
 7454	clause_status(Lits,Key,[],legal,Status1,M),
 7455	Status1 = Status, !,
 7456        (Key = false ->
 7457        	get_pclause(Lits,[],C,_,_,_,M);
 7458        	get_pclause(Lits,Key,[],C,_,_,_,M)).
 7459
 7460% clause_status(+Lits,+LitsSoFar,+StatusSoFar,-Status,M)
 7461% compute status of a clause
 7462%	Lits is the lits left to add to the clause
 7463%	LitsSoFar is the lits in the clause so far
 7464%	StatusSoFar is the Status of the clause so far
 7465%		if a literal to be added contains unbound input vars then
 7466%		status is illegal
 7467clause_status(Lits,LitsSoFar,Status1,Status2,M):-
 7468	bottom_key(_,_,Key,_,M),
 7469	clause_status(Lits,Key,LitsSoFar,Status1,Status2,M).
 7470
 7471clause_status([],_,_,S,S,_M):- !.
 7472clause_status([Lit|Lits],Key,LitsSoFar,S,S1,M):-
 7473	get_ovars(LitsSoFar,Key,[],OVars,M),
 7474	get_ivars([Lit],Key,[],IVars,M),
 7475	aleph_subset1(IVars,OVars), !,
 7476	aleph_append([Lit],LitsSoFar,Lits1),
 7477	clause_status(Lits,Key,Lits1,S,S1,M).
 7478clause_status(_,_,_,_,illegal,_M).
 7479
 7480	
 7481% randselect(+L,+Last,+Key,+LitsSoFar,-Lits,M)
 7482% randomly select L distinct literals to give Lits
 7483% Last is the last literal number in the bottom clause
 7484% LitsSoFar is the literals selected so far
 7485randselect(0,_,_,_,[],_M):- !.
 7486randselect(_,Last,_,LitsSoFar,[],_M):-
 7487        length(LitsSoFar,L1),
 7488        L1 is Last - 1, !.
 7489randselect(L,Last,Key,LitsSoFar,[LitNum|Lits],M):-
 7490	get_rand_lit(Last,Key,LitsSoFar,LitNum,M),
 7491	L1 is L - 1,
 7492	randselect(L1,Last,Key,[LitNum|LitsSoFar],Lits,M).
 7493
 7494% randselect1(+L,+Key,+Avail,+LitsSoFar,-Lits,M)
 7495% randomly select L distinct literals from Avail to give Lits
 7496% LitsSoFar is the literals selected so far
 7497randselect1(0,_,_,_,[],_M):- !.
 7498randselect1(_,_,[],_,[],_M):- !.
 7499randselect1(L,Key,Avail,LitsSoFar,[LitNum|Lits],M):-
 7500	random_select(LitNum,Avail,Left),
 7501	(Key = false ->
 7502        	M:'$aleph_sat_litinfo'(LitNum,_,_,_,_,D);
 7503        	M:'$aleph_sat_litinfo'(LitNum,Key,_,_,_,_,D)), 
 7504        update_list(D,Left,Left1),
 7505        aleph_delete_list([LitNum|LitsSoFar],Left1,Avail1),
 7506        L1 is L - 1,
 7507        randselect1(L1,Key,Avail1,[LitNum|LitsSoFar],Lits,M).
 7508 
 7509% get_rand_lit(+Last,+Key,+LitsSoFar,-LitNum,M)
 7510% randomly select a literal number from 2 - Last
 7511% and not in list LitsSoFar
 7512%	2 because 1 is reserved for head literal
 7513get_rand_lit(Last,Key,LitsSoFar,LitNum,M):-
 7514	repeat,
 7515	get_rand_lit(Last,Key,LitNum,M),
 7516	\+(aleph_member(LitNum,LitsSoFar)),
 7517	!.
 7518
 7519% have to use repeat/0 in case literal number from random no generator
 7520%	no longer exists in lits database
 7521get_rand_lit(Last,Key,LitNum,M):-
 7522	repeat,
 7523	get_random(Last,LitNum),
 7524	LitNum > 1,
 7525	(Key = false ->
 7526        	M:'$aleph_sat_litinfo'(LitNum,_,_,_,_,_);
 7527        	M:'$aleph_sat_litinfo'(LitNum,Key,_,_,_,_,_)), !.
 7528
 7529% total_clauses(+L,+N1,-N2)
 7530%	total number of clauses of length L is N2
 7531%	constructed from bottom clause of length N1
 7532total_clauses(1,_,1.0):- !.
 7533total_clauses(L,Bot,N):-
 7534	L1 is L - 1,
 7535	Bot1 is Bot - 1,
 7536	total_clauses(L1,Bot1,N1),
 7537	N is N1*Bot1.
 7538
 7539% num_to_length(+N,+CL,-L,M)
 7540%	find length of clause numbered N
 7541%	clause length should be =< CL
 7542
 7543num_to_length(N,_,1,_M):- N =< 1.0, !.
 7544num_to_length(N,CL,L,M):-
 7545	num_to_length1(2,CL,N,1.0,L,M).
 7546
 7547num_to_length1(L,CL,_,_,CL,_M):-
 7548	L >= CL, !.
 7549num_to_length1(L,CL,N,TotalSoFar,Length,M):-
 7550	M:'$aleph_sat'(random,number_of_clauses(L,T)),
 7551	NClauses is TotalSoFar + T,
 7552	(N =< NClauses ->  
 7553		(T < 1.0 -> Length is L - 1; Length = L) ;
 7554		L1 is L + 1,
 7555		num_to_length1(L1,CL,N,NClauses,Length,M)).
 7556
 7557% refinement operator for randomised local search
 7558%	Type is one of clauses or theories
 7559rls_refine(clauses,_-[_,_,_,aleph_false],Clause,M):-
 7560	!,
 7561	sample_clauses(1,[Clause],M),
 7562	\+(old_move(clauses,Clause,M)).
 7563rls_refine(clauses,Clause1,Clause2,M):-
 7564	setting(moves,Max,M),
 7565	MaxMoves is Max,
 7566	once(retract(M:'$aleph_search'(rls_move,Mov))),
 7567	Mov =< MaxMoves,
 7568	p1_message('move'), p_message(Mov),
 7569	Mov1 is Mov + 1,
 7570	asserta(M:'$aleph_search'(rls_move,Mov1)),
 7571	clause_move(Move,Clause1,Clause2,M),
 7572	p_message(Move),
 7573	\+(old_move(clauses,Clause2,M)).
 7574
 7575rls_refine(theories,[_-[_,_,_,aleph_false]],Theory,M):-
 7576	!,
 7577	once(theory_move(add_clause,[],Theory,M)),
 7578	\+(old_move(theories,Theory,M)).
 7579rls_refine(theories,Theory1,Theory2,M):-
 7580	setting(moves,MaxMoves,M),
 7581	once(retract(M:'$aleph_search'(rls_move,M))),
 7582	M =< MaxMoves,
 7583	p1_message('move'), p_message(M),
 7584	M1 is M + 1,
 7585	asserta(M:'$aleph_search'(rls_move,M1)),
 7586	theory_move(_,Theory1,Theory2,M),
 7587	\+(old_move(theories,Theory2,M)).
 7588
 7589% clause_move(+Type,+C1,-C2,M)
 7590% local moves from clause C1 to give C2
 7591%	A move is:
 7592%	a) delete a literal from C1 (Type = delete_lit)
 7593%	b) add a legal literal to C1 (Type = add_lit)
 7594clause_move(delete_lit,C1,C2,M):-
 7595	C1 = L-[E,T,Lits,Clause],
 7596	(Lits = [H|Rest] ->
 7597		aleph_delete(_,Rest,Left),
 7598		Lits1 = [H|Left],
 7599		bottom_key(E,T,Key,_,M),
 7600		clause_status(Lits1,Key,[],legal,legal,M),
 7601		L1 is L - 1,
 7602		(Key = false ->
 7603        		get_pclause(Lits1,[],Clause1,_,_,_,M);
 7604        		get_pclause(Lits1,Key,[],Clause1,_,_,_,M)),
 7605		\+(M:prune(Clause1)) ;
 7606		clause_to_list(Clause,[Head|Body]),
 7607		aleph_delete(_,Body,Left),
 7608		aleph_mode_linked([Head|Left],M),
 7609		list_to_clause([Head|Left],Clause1),
 7610		\+(M:prune(Clause1)),
 7611		L1 is L - 1,
 7612		Lits1 = []),
 7613	C2 = L1-[E,T,Lits1,Clause1].
 7614clause_move(add_lit,C1,C2,M):-
 7615	C1 = L-[E,T,Lits,Clause],
 7616	setting(clauselength,CL,M),
 7617	L < CL,
 7618	(Lits = [] ->
 7619		auto_refine(Clause,Clause1,M),
 7620		L1 is L + 1,
 7621		Lits1 = [];
 7622		aleph_delete(Lit,Lits,Left),
 7623		bottom_key(E,T,Key,_,M),
 7624		(Key = false ->
 7625        		M:'$aleph_sat_litinfo'(Lit,_,_,_,_,D);
 7626        		M:'$aleph_sat_litinfo'(Lit,Key,_,_,_,_,D)),
 7627		aleph_member(Lit1,D),
 7628		\+(aleph_member(Lit1,Left)),
 7629		aleph_append([Lit1],Lits,Lits1),
 7630        	clause_status(Lits1,Key,[],legal,legal,M),
 7631		L1 is L + 1,
 7632		(Key = false ->
 7633        		get_pclause(Lits1,[],Clause1,_,_,_,M);
 7634        		get_pclause(Lits1,Key,[],Clause1,_,_,_,M)),
 7635		\+(M:prune(Clause1))),
 7636	C2 = L1-[E,T,Lits1,Clause1].
 7637
 7638% theory_move(+Type,+T1,-T2,M)
 7639% local moves from theory T1 to give T2
 7640%	A move is:
 7641%	a) delete a clause from T1 (Type = delete_clause)
 7642%	b) add a legal clause to  T1  (Type = add_clause)
 7643%	c) delete a literal from a clause in T1 (Type = delete_lit)
 7644%	d) add a legal literal to a clause in T1 (Type = add_lit)
 7645theory_move(delete_clause,T1,T2,_M):-
 7646	aleph_delete(_,T1,T2),
 7647	T2 \= [].
 7648theory_move(add_clause,T1,T2,M):-
 7649	setting(clauses,Max,M),
 7650	length(T1,L),
 7651	L < Max,
 7652	sample_clauses(1,[Clause],M),
 7653	aleph_append([Clause],T1,T2).
 7654theory_move(delete_lit,T1,T2,M):-
 7655	aleph_delete(Clause,T1,T),
 7656	clause_move(delete_lit,Clause,Clause1,M),
 7657	aleph_append([Clause1],T,T2).
 7658theory_move(add_lit,T1,T2,M):-
 7659	aleph_delete(Clause,T1,T),
 7660	clause_move(add_lit,Clause,Clause1,M),
 7661	aleph_append([Clause1],T,T2).
 7662
 7663old_move(clauses,N-[_,_,L,C],M):-
 7664	(setting(cache_clauselength,N1,M) -> true; N1 = 3),
 7665	N =< N1,
 7666	(L = [] ->
 7667		clause_to_list(C,C1),
 7668		sort(C1,Hash),
 7669		numbervars(Hash,0,_);
 7670		sort(L,Hash)),
 7671	(M:'$aleph_search_seen'(N,Hash) ->
 7672		p_message('old move'),
 7673		true;
 7674		asserta(M:'$aleph_search_seen'(N,Hash)), !,
 7675		fail).
 7676old_move(theories,T,M):-
 7677	% remove_alpha_variants(T,T1),
 7678	numbervars(T,0,_),
 7679	length(T,N),
 7680	(M:'$aleph_search_seen'(N,_Hash) ->
 7681		p_message('old move'),
 7682		true;
 7683		asserta(M:'$aleph_search_seen'(N,_Hash)), !,
 7684		fail).
 7685		
 7686extract_clauses_with_length([],[]).
 7687extract_clauses_with_length([L-[_,_,_,C]|T],[L-C|T1]):-
 7688	extract_clauses_with_length(T,T1).
 7689
 7690%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 7691% U T I L I T I E S
 7692
 7693% concatenate elements of a list into an atom
 7694
 7695concat([Atom],Atom):- !.
 7696concat([H|T],Atom):-
 7697        concat(T,AT),
 7698        name(AT,L2),
 7699        name(H,L1),
 7700        aleph_append(L2,L1,L),
 7701        name(Atom,L).
 7702
 7703
 7704split_clause((Head:-true),Head,true):- !.
 7705split_clause((Head:-Body1),Head,Body2):- !, Body1 = Body2.
 7706split_clause([Head|T],Head,T):- !.
 7707split_clause([Head],Head,[true]):- !.
 7708split_clause(Head,Head,true).
 7709
 7710strip_true((Head:-true),Head):- !.
 7711strip_true(Clause,Clause).
 7712
 7713% pretty print a definite clause
 7714pp_dclause(Clause,M):-
 7715        (M:'$aleph_global'(portray_literals,set(portray_literals,true))->
 7716                pp_dclause(Clause,true,M);
 7717                pp_dclause(Clause,false,M)).
 7718
 7719% pretty print a set of definite clauses
 7720pp_dclauses(Theory,M):-
 7721        aleph_member(_-[_,_,_,Clause],Theory),
 7722        pp_dclause(Clause,M),
 7723        fail.
 7724pp_dclauses(_,_M):- nl.
 7725 
 7726pp_dclause((H:-true),Pretty,M):-
 7727        !,
 7728        pp_dclause(H,Pretty,M).
 7729pp_dclause((H:-B),Pretty,M):-
 7730        !,
 7731        copy_term((H:-B),(Head:-Body)),
 7732        numbervars((Head:-Body),0,_),
 7733        aleph_portray(Head,Pretty,M),
 7734        (Pretty = true ->
 7735                write(' if:');
 7736                write(' :-')),
 7737        nl,
 7738        M:'$aleph_global'(print,set(print,N)),
 7739        print_lits(Body,Pretty,1,N,M).
 7740
 7741pp_dclause((Lit),Pretty,M):-
 7742        copy_term(Lit,Lit1),
 7743        numbervars(Lit1,0,_),
 7744        aleph_portray(Lit1,Pretty,M),
 7745        write('.'), nl.
 7746 
 7747% pretty print a definite clause list: head of list is + literal
 7748pp_dlist([],_M):- !.
 7749pp_dlist(Clause,M):-
 7750        (M:'$aleph_global'(portray_literals,set(portray_literals,true))->
 7751                pp_dlist(Clause,true,M);
 7752                pp_dlist(Clause,false,M)).
 7753 
 7754pp_dlist(Clause,Pretty,M):-
 7755        copy_term(Clause,[Head1|Body1]),
 7756        numbervars([Head1|Body1],0,_),
 7757        aleph_portray(Head1,Pretty,M),
 7758        (Body1 = [] ->
 7759                write('.'), nl;
 7760                (Pretty = true ->
 7761                        write(' if:');
 7762                        write(' :-')),
 7763        nl,
 7764        M:'$aleph_global'(print,set(print,N)),
 7765        print_litlist(Body1,Pretty,1,N,M)).
 7766 
 7767print_litlist([],_,_,_,_M).
 7768print_litlist([Lit],Pretty,LitNum,_,M):-
 7769        !,
 7770        print_lit(Lit,Pretty,LitNum,LitNum,'.',_,M).
 7771print_litlist([Lit|Lits],Pretty,LitNum,LastLit,M):-
 7772        print_lit(Lit,Pretty,LitNum,LastLit,', ',NextLit,M),
 7773        print_litlist(Lits,Pretty,NextLit,LastLit,M).
 7774 
 7775print_lits((Lit,Lits),Pretty,LitNum,LastLit,M):-
 7776        !,
 7777        (Pretty = true ->
 7778                Sep = ' and ';
 7779                Sep = ', '),
 7780        print_lit(Lit,Pretty,LitNum,LastLit,Sep,NextLit,M),
 7781        print_lits(Lits,Pretty,NextLit,LastLit,M).
 7782print_lits((Lit),Pretty,LitNum,_,M):-
 7783        print_lit(Lit,Pretty,LitNum,LitNum,'.',_,M).
 7784
 7785print_lit(Lit,Pretty,LitNum,LastLit,Sep,NextLit,M):-
 7786        (LitNum = 1 -> tab(3);true),
 7787        aleph_portray(Lit,Pretty,M), write(Sep),
 7788        (LitNum=LastLit-> nl,NextLit=1; NextLit is LitNum + 1).
 7789 
 7790p1_message(Mess):-
 7791	write('['), write(Mess), write('] ').
 7792
 7793p_message(Mess):-
 7794	write('['), write(Mess), write(']'), nl.
 7795
 7796err_message(Mess):-
 7797	p1_message('error'), p_message(Mess).
 7798
 7799aleph_delete_all(_,[],[]).
 7800aleph_delete_all(X,[Y|T],T1):-
 7801        X == Y, !,
 7802        aleph_delete_all(X,T,T1).
 7803aleph_delete_all(X,[Y|T],[Y|T1]):-
 7804        aleph_delete_all(X,T,T1).
 7805
 7806aleph_delete_list([],L,L).
 7807aleph_delete_list([H1|T1],L1,L):-
 7808	aleph_delete(H1,L1,L2), !,
 7809	aleph_delete_list(T1,L2,L).
 7810aleph_delete_list([_|T1],L1,L):-
 7811	aleph_delete_list(T1,L1,L).
 aleph_delete(-El:term, -List:list, -Rest:list) is nondet
Deletes element from list. /
 7818aleph_delete(H,[H|T],T).
 7819aleph_delete(H,[H1|T],[H1|T1]):-
 7820	aleph_delete(H,T,T1).
 7821
 7822aleph_delete1(H,[H|T],T):- !.
 7823aleph_delete1(H,[H1|T],[H1|T1]):-
 7824	aleph_delete1(H,T,T1).
 7825
 7826aleph_delete0(_,[],[]).
 7827aleph_delete0(H,[H|T],T):- !.
 7828aleph_delete0(H,[H1|T],[H1|T1]):-
 7829	aleph_delete0(H,T,T1).
 7830
 7831aleph_append(A,[],A):-!.
 7832aleph_append(A,[H|T],[H|T1]):-
 7833	aleph_append(A,T,T1).
 7834
 7835% aleph_remove_nth(+N,+List1,-Elem,-List2)
 7836%	remove the nth elem from a List
 7837aleph_remove_nth(1,[H|T],H,T):- !.
 7838aleph_remove_nth(N,[H|T],X,[H|T1]):-
 7839        N1 is N - 1,
 7840        aleph_remove_nth(N1,T,X,T1).
 7841
 7842% aleph_remove_n(+N,+List1,-List2,-List3)
 7843%	remove the n elems from List1 into List2. List3 is the rest of List1
 7844aleph_remove_n(0,L,[],L):- !.
 7845aleph_remove_n(_,[],[],[]):- !.
 7846aleph_remove_n(N,[H|T],[H|T1],L):-
 7847	N1 is N - 1,
 7848	aleph_remove_n(N1,T,T1,L).
 7849
 7850% aleph_rpermute(+List1,-List2)
 7851%	randomly permute the elements of List1 into List2
 7852aleph_rpermute(List1,List2):-
 7853	length(List1,N1),
 7854	aleph_rpermute(List1,N1,List2).
 7855
 7856aleph_rpermute([],0,[]):- !.
 7857aleph_rpermute(L1,N1,[X|Rest]):-
 7858	get_random(N1,R),
 7859	aleph_remove_nth(R,L1,X,L2),
 7860	N2 is N1 - 1,
 7861	aleph_rpermute(L2,N2,Rest).
 7862
 7863% aleph_rsample(+N,+List1,-List2)
 7864%	randomly sample N elements from List1 into List2
 7865aleph_rsample(N,List1,List2):-
 7866	length(List1,N1),
 7867	aleph_rsample(N,N1,List1,List2).
 7868
 7869aleph_rsample(N,N1,L,L):- N >= N1, !.
 7870aleph_rsample(SampleSize,Total,[X|L1],[X|L2]):-
 7871	get_random(Total,R),
 7872	R =< SampleSize, !,
 7873	SampleSize0 is SampleSize - 1,
 7874	Total0 is Total - 1,
 7875	aleph_rsample(SampleSize0,Total0,L1,L2).
 7876aleph_rsample(SampleSize,Total,[_|L1],L2):-
 7877	Total0 is Total - 1,
 7878	aleph_rsample(SampleSize,Total0,L1,L2).
 7879
 7880% get_first_n(+N,+List1,-List2)
 7881%	get the first n elements in List1
 7882get_first_n(0,_,[]):- !.
 7883get_first_n(_,[],[]):- !.
 7884get_first_n(N,[H|T],[H|T1]):-
 7885	N1 is N - 1,
 7886	get_first_n(N1,T,T1).
 7887
 7888% erase_refs(+List)
 7889%	erase database references: only works for Yap
 7890erase_refs([]).
 7891erase_refs([DbRef|DbRefs]):-
 7892	erase(DbRef),
 7893	erase_refs(DbRefs).
 7894
 7895
 7896% max_in_list(+List,-Max)
 7897%	return largest element in a list
 7898max_in_list([X],X):- !.
 7899max_in_list([X|T],Z):-
 7900	max_in_list(T,Y),
 7901	(X @> Y -> Z = X; Z = Y). 
 7902
 7903% min_in_list(+List,-Max)
 7904%	return largest element in a list
 7905min_in_list([X],X):- !.
 7906min_in_list([X|T],Z):-
 7907	min_in_list(T,Y),
 7908	(X @> Y -> Z = Y; Z = X). 
 7909
 7910% remove_alpha_variants(+List1,-List2):-
 7911%	remove alphabetic variants from List1 to give List2
 7912remove_alpha_variants([],[]).
 7913remove_alpha_variants([X|Y],L):-
 7914	aleph_member(X1,Y),
 7915	alphabetic_variant(X,X1), !,
 7916	remove_alpha_variants(Y,L).
 7917remove_alpha_variants([X|Y],[X|L]):-
 7918	remove_alpha_variants(Y,L).
 7919 
 7920% alphabetic_variant(+Term1,+Term2)
 7921%	true if Term1 is the alphabetic variant of Term2
 7922alphabetic_variant(Term1,Term2):-
 7923	copy_term(Term1/Term2,T1/T2),
 7924	numbervars(T1,0,_),
 7925	numbervars(T2,0,_),
 7926	T1 = T2.
 7927
 7928% tparg(+TermPlace,+Term1,?Term2)
 7929% return Term2 at position specified by TermPlace in Term1
 7930tparg([Place],Term,Arg):-
 7931        !,
 7932        arg(Place,Term,Arg).
 7933tparg([Place|Places],Term,Arg):-
 7934        arg(Place,Term,Term1),
 7935        tparg(Places,Term1,Arg).
 7936
 7937
 7938aleph_member1(H,[H|_]):- !.
 7939aleph_member1(H,[_|T]):-
 7940	aleph_member1(H,T).
 7941
 7942aleph_member2(X,[Y|_]):- X == Y, !.
 7943aleph_member2(X,[_|T]):-
 7944	aleph_member2(X,T).
 7945
 7946aleph_member3(A,A-B):- A =< B.
 7947aleph_member3(X,A-B):-
 7948	A < B,
 7949	A1 is A + 1,
 7950	aleph_member3(X,A1-B).
 7951
 7952aleph_member(X,[X|_]).
 7953aleph_member(X,[_|T]):-
 7954	aleph_member(X,T).
 7955
 7956aleph_reverse(L1, L2) :- revzap(L1, [], L2).
 7957
 7958revzap([X|L], L2, L3) :- revzap(L, [X|L2], L3).
 7959revzap([], L, L).
 7960
 7961goals_to_clause((Head,Body),(Head:-Body)):- !.
 7962goals_to_clause(Head,Head).
 clause_to_list(+Cl:term, -List:list) is det
From a clause to a list /
 7969clause_to_list((Head:-true),[Head]):- !.
 7970clause_to_list((Head:-Body),[Head|L]):-
 7971        !,
 7972        goals_to_list(Body,L).
 7973clause_to_list(Head,[Head]).
 7974
 7975extend_clause(false,Lit,(Lit)):- !.
 7976extend_clause((Head:-Body),Lit,(Head:-Body1)):-
 7977        !,
 7978        app_lit(Lit,Body,Body1).
 7979extend_clause(Head,Lit,(Head:-Lit)).
 7980 
 7981app_lit(L,(L1,L2),(L1,L3)):-
 7982        !,
 7983        app_lit(L,L2,L3).
 7984app_lit(L,L1,(L1,L)).
 7985
 7986prefix_lits(L,true,L):- !.
 7987prefix_lits(L,L1,((L),L1)).
 7988
 7989get_goaldiffs((G1,G2),(G1,G3),Diffs):-
 7990	!,
 7991	get_goaldiffs(G2,G3,Diffs).
 7992get_goaldiffs(true,G,G):- !.
 7993get_goaldiffs(G1,(G1,G2),G2).
 7994
 7995nlits((_:-B),N):-
 7996	!,
 7997	nlits(B,N1),
 7998	N is N1 + 1.
 7999nlits((_,Lits),N):-
 8000	!,
 8001	nlits(Lits,N1),
 8002	N is N1 + 1.
 8003nlits(_,1).
 8004
 8005
 8006list_to_clause([Goal],(Goal:-true)):- !.
 8007list_to_clause([Head|Goals],(Head:-Body)):-
 8008	list_to_goals(Goals,Body).
 8009
 8010list_to_goals([Goal],Goal):- !.
 8011list_to_goals([Goal|Goals],(Goal,Goals1)):-
 8012	list_to_goals(Goals,Goals1).
 goals_to_list(-Goals:term, -List:list) is det
Converts a coonjunction of goals to a list

/

 8020goals_to_list((true,Goals),T):-
 8021	!,
 8022	goals_to_list(Goals,T).
 8023goals_to_list((Goal,Goals),[Goal|T]):-
 8024	!,
 8025	goals_to_list(Goals,T).
 8026goals_to_list(true,[]):- !.
 8027goals_to_list(Goal,[Goal]).
 8028
 8029% get_litnums(+First,+Last,-LitNums,M)
 8030%	get list of Literal numbers in the bottom clause
 8031get_litnums(LitNum,Last,[],_M):-
 8032        LitNum > Last, !.
 8033get_litnums(LitNum,Last,[LitNum|LitNums],M):-
 8034        M:'$aleph_sat_litinfo'(LitNum,_,_,_,_,_), !,
 8035        NextLit is LitNum + 1,
 8036        get_litnums(NextLit,Last,LitNums,M).
 8037get_litnums(LitNum,Last,LitNums,M):-
 8038        NextLit is LitNum + 1,
 8039        get_litnums(NextLit,Last,LitNums,M).
 8040
 8041get_clause(LitNum,Last,_,[],_M):-
 8042        LitNum > Last, !.
 8043get_clause(LitNum,Last,TVSoFar,[FAtom|FAtoms],M):-
 8044        M:'$aleph_sat_litinfo'(LitNum,_,Atom,_,_,_), !,
 8045        get_flatatom(Atom,TVSoFar,FAtom,TV1),
 8046        NextLit is LitNum + 1,
 8047        get_clause(NextLit,Last,TV1,FAtoms,M).
 8048get_clause(LitNum,Last,TVSoFar,FAtoms,M):-
 8049        NextLit is LitNum + 1,
 8050        get_clause(NextLit,Last,TVSoFar,FAtoms,M).
 8051
 8052get_flatatom(not(Atom),TVSoFar,not(FAtom),TV1):-
 8053        !,
 8054        get_flatatom(Atom,TVSoFar,FAtom,TV1).
 8055get_flatatom(Atom,TVSoFar,FAtom,TV1):-
 8056        functor(Atom,Name,Arity),
 8057        functor(FAtom,Name,Arity),
 8058        flatten_args(Arity,Atom,FAtom,TVSoFar,TV1).
 8059
 8060get_pclause([LitNum],TVSoFar,Clause,TV,Length,LastDepth,M):-
 8061        !,
 8062        get_pclause1([LitNum],TVSoFar,TV,Clause,Length,LastDepth,M).
 8063get_pclause([LitNum|LitNums],TVSoFar,Clause,TV,Length,LastDepth,M):-
 8064        get_pclause1([LitNum],TVSoFar,TV1,Head,Length1,_,M),
 8065        get_pclause1(LitNums,TV1,TV,Body,Length2,LastDepth,M),
 8066	Clause = (Head:-Body),
 8067        Length is Length1 + Length2.
 8068
 8069get_pclause1([LitNum],TVSoFar,TV1,Lit,Length,LastDepth,M):-
 8070        !,
 8071        M:'$aleph_sat_litinfo'(LitNum,LastDepth,Atom,_,_,_),
 8072        get_flatatom(Atom,TVSoFar,Lit,TV1),
 8073        functor(Lit,Name,_),
 8074        (Name = '='-> Length = 0; Length = 1).
 8075get_pclause1([LitNum|LitNums],TVSoFar,TV2,(Lit,Lits1),Length,LastDepth,M):-
 8076        M:'$aleph_sat_litinfo'(LitNum,_,Atom,_,_,_),
 8077        get_flatatom(Atom,TVSoFar,Lit,TV1),
 8078        get_pclause1(LitNums,TV1,TV2,Lits1,Length1,LastDepth,M),
 8079        functor(Lit,Name,_),
 8080        (Name = '='-> Length = Length1; Length is Length1 + 1).
 8081
 8082get_pclause([LitNum],Key,TVSoFar,Clause,TV,Length,LastDepth,M):-
 8083        !,
 8084        get_pclause1([LitNum],Key,TVSoFar,TV,Clause,Length,LastDepth,M).
 8085get_pclause([LitNum|LitNums],Key,TVSoFar,Clause,TV,Length,LastDepth,M):-
 8086        get_pclause1([LitNum],Key,TVSoFar,TV1,Head,Length1,_,M),
 8087        get_pclause1(LitNums,Key,TV1,TV,Body,Length2,LastDepth,M),
 8088	Clause = (Head:-Body),
 8089        Length is Length1 + Length2.
 8090
 8091get_pclause1([LitNum],Key,TVSoFar,TV1,Lit,Length,LastDepth,M):-
 8092        !,
 8093        M:'$aleph_sat_litinfo'(LitNum,Key,LastDepth,Atom,_,_,_),
 8094        get_flatatom(Atom,TVSoFar,Lit,TV1),
 8095        functor(Lit,Name,_),
 8096        (Name = '='-> Length = 0; Length = 1).
 8097get_pclause1([LitNum|LitNums],Key,TVSoFar,TV2,(Lit,Lits1),Length,LastDepth,M):-
 8098        M:'$aleph_sat_litinfo'(LitNum,Key,_,Atom,_,_,_),
 8099        get_flatatom(Atom,TVSoFar,Lit,TV1),
 8100        get_pclause1(LitNums,Key,TV1,TV2,Lits1,Length1,LastDepth,M),
 8101        functor(Lit,Name,_),
 8102        (Name = '='-> Length = Length1; Length is Length1 + 1).
 8103
 8104
 8105flatten_args(0,_,_,TV,TV):- !.
 8106flatten_args(Arg,Atom,FAtom,TV,TV1):-
 8107        arg(Arg,Atom,Term),
 8108        Arg1 is Arg - 1,
 8109        (Term = aleph_const(Const) ->
 8110                arg(Arg,FAtom,Const),
 8111                flatten_args(Arg1,Atom,FAtom,TV,TV1);
 8112                (integer(Term) ->
 8113                        update(TV,Term/Var,TV0),
 8114                        arg(Arg,FAtom,Var),
 8115                        flatten_args(Arg1,Atom,FAtom,TV0,TV1);
 8116                        (functor(Term,Name,Arity),
 8117                         functor(FTerm,Name,Arity),
 8118                         arg(Arg,FAtom,FTerm),
 8119                         flatten_args(Arity,Term,FTerm,TV,TV0),
 8120                         flatten_args(Arg1,Atom,FAtom,TV0,TV1)
 8121                        )
 8122                )
 8123        ).
 8124
 8125
 8126% returns intersection of S1, S2 and S1-Intersection
 8127intersect1(Elems,[],[],Elems):- !.
 8128intersect1([],_,[],[]):- !.
 8129intersect1([Elem|Elems],S2,[Elem|Intersect],ElemsLeft):-
 8130	aleph_member1(Elem,S2), !,
 8131	intersect1(Elems,S2,Intersect,ElemsLeft).
 8132intersect1([Elem|Elems],S2,Intersect,[Elem|ElemsLeft]):-
 8133	intersect1(Elems,S2,Intersect,ElemsLeft).
 8134
 8135aleph_subset1([],_).
 8136aleph_subset1([Elem|Elems],S):-
 8137	aleph_member1(Elem,S), !,
 8138	aleph_subset1(Elems,S).
 8139
 8140aleph_subset2([X|Rest],[X|S]):-
 8141	aleph_subset2(Rest,S).
 8142aleph_subset2(S,[_|S1]):-
 8143	aleph_subset2(S,S1).
 8144aleph_subset2([],[]).
 8145
 8146% two sets are equal
 8147
 8148equal_set([],[]).
 8149equal_set([H|T],S):-
 8150	aleph_delete1(H,S,S1),
 8151	equal_set(T,S1), !.
 8152
 8153uniq_insert(_,X,[],[X]).
 8154uniq_insert(descending,H,[H1|T],[H,H1|T]):-
 8155	H @> H1, !.
 8156uniq_insert(ascending,H,[H1|T],[H,H1|T]):-
 8157	H @< H1, !.
 8158uniq_insert(_,H,[H|T],[H|T]):- !.
 8159uniq_insert(Order,H,[H1|T],[H1|T1]):-
 8160	!,
 8161	uniq_insert(Order,H,T,T1).
 8162
 8163quicksort(_,[],[]).
 8164quicksort(Order,[X|Tail],Sorted):-
 8165	partition(X,Tail,Small,Big),
 8166	quicksort(Order,Small,SSmall),
 8167	quicksort(Order,Big,SBig),
 8168        (Order=ascending-> aleph_append([X|SBig],SSmall,Sorted);
 8169                aleph_append([X|SSmall],SBig,Sorted)).
 8170	
 8171partition(_,[],[],[]).
 8172partition(X,[Y|Tail],[Y|Small],Big):-
 8173	X @> Y, !,
 8174	partition(X,Tail,Small,Big).
 8175partition(X,[Y|Tail],Small,[Y|Big]):-
 8176	partition(X,Tail,Small,Big).
 8177
 8178update_list([],L,L).
 8179update_list([H|T],L,Updated):-
 8180	update(L,H,L1), !,
 8181	update_list(T,L1,Updated).
 8182
 8183update([],H,[H]).
 8184update([H|T],H,[H|T]):- !.
 8185update([H1|T],H,[H1|T1]):-
 8186	update(T,H,T1).
 8187
 8188% checks if 2 sets intersect
 8189intersects(S1,S2):-
 8190	aleph_member(Elem,S1), aleph_member1(Elem,S2), !.
 8191
 8192% checks if bitsets represented as lists of intervals intersect
 8193intervals_intersects([L1-L2|_],I):-
 8194	intervals_intersects1(L1-L2,I), !.
 8195intervals_intersects([_|I1],I):-
 8196	intervals_intersects(I1,I).
 8197
 8198intervals_intersects1(L1-_,[M1-M2|_]):-
 8199	L1 >= M1, L1 =< M2, !.
 8200intervals_intersects1(L1-L2,[M1-_|_]):-
 8201	M1 >= L1, M1 =< L2, !.
 8202intervals_intersects1(L1-L2,[_|T]):-
 8203	intervals_intersects1(L1-L2,T).
 8204
 8205% checks if bitsets represented as lists of intervals intersect
 8206% returns first intersection
 8207intervals_intersects([L1-L2|_],I,I1):-
 8208	intervals_intersects1(L1-L2,I,I1), !.
 8209intervals_intersects([_|ILeft],I,I1):-
 8210	intervals_intersects(ILeft,I,I1).
 8211
 8212intervals_intersects1(I1,[I2|_],I):-
 8213	interval_intersection(I1,I2,I), !.
 8214intervals_intersects1(I1,[_|T],I):-
 8215	intervals_intersects1(I1,T,I).
 8216
 8217interval_intersection(L1-L2,M1-M2,L1-L2):-
 8218	L1 >= M1, L2 =< M2, !.
 8219interval_intersection(L1-L2,M1-M2,M1-M2):-
 8220	M1 >= L1, M2 =< L2, !.
 8221interval_intersection(L1-L2,M1-M2,L1-M2):-
 8222	L1 >= M1, M2 >= L1, M2 =< L2, !.
 8223interval_intersection(L1-L2,M1-M2,M1-L2):-
 8224	M1 >= L1, M1 =< L2, L2 =< M2, !.
 8225
 8226%most of the time no intersection, so optimise on that
 8227% optimisation by James Cussens
 8228intervals_intersection([],_,[]).
 8229intervals_intersection([A-B|T1],[C-D|T2],X) :-
 8230        !,
 8231        (A > D ->
 8232            intervals_intersection([A-B|T1],T2,X);
 8233            (C > B ->
 8234                intervals_intersection(T1,[C-D|T2],X);
 8235                (B > D ->
 8236                    (C > A ->
 8237                        X=[C-D|Y];
 8238                        X=[A-D|Y]
 8239                    ),
 8240                    intervals_intersection([A-B|T1],T2,Y);
 8241                    (C > A ->
 8242                        X=[C-B|Y];
 8243                        X=[A-B|Y]
 8244                    ),
 8245                    intervals_intersection(T1,[C-D|T2],Y)
 8246                )
 8247            )
 8248        ).
 8249intervals_intersection(_,[],[]).
 8250
 8251
 8252% finds length of intervals in a list
 8253interval_count([],0).
 8254interval_count([L1-L2|T],N):-
 8255	N1 is L2 - L1 + 1,
 8256	interval_count(T,N2),
 8257	N is N1 + N2.
 8258interval_count(I/_,N):-
 8259	interval_count(I,N).
 8260
 8261% interval_select(+N,+List1,-Elem)
 8262%       select the Nth elem from an interval list
 8263interval_select(N,[A-B|_],X):-
 8264        N =< B - A + 1, !,
 8265        X is A + N - 1.
 8266interval_select(N,[A-B|T],X):-
 8267        N1 is N - (B - A + 1),
 8268        interval_select(N1,T,X).
 8269
 8270% interval_sample(+N,List1,-List2)
 8271%	get a random sample of N elements from List1
 8272interval_sample(N,List1,List2):-
 8273	intervals_to_list(List1,L1),
 8274	aleph_rsample(N,L1,L2),
 8275	list_to_intervals(L2,List2).
 8276
 8277% convert list to intervals
 8278list_to_intervals(List,Intervals):-
 8279	sort(List,List1),
 8280        list_to_intervals1(List1,Intervals).
 8281
 8282list_to_intervals1([],[]).
 8283list_to_intervals1([Start|T],[Start-Finish|I1]):-
 8284        list_to_interval(Start,T,Finish,T1),
 8285        list_to_intervals1(T1,I1).
 8286
 8287list_to_interval(Finish,[],Finish,[]).
 8288list_to_interval(Finish,[Next|T],Finish,[Next|T]):-
 8289        Next - Finish > 1,
 8290        !.
 8291list_to_interval(_,[Start|T],Finish,Rest):-
 8292        list_to_interval(Start,T,Finish,Rest).
 8293
 8294% converts an interval-list into a list of (sorted) numbers
 8295intervals_to_list(L,L1):-
 8296	intervals_to_list(L,[],L0),
 8297	sort(L0,L1), !.
 8298
 8299intervals_to_list([],L,L).
 8300intervals_to_list([Interval|Intervals],L1,L2):-
 8301	interval_to_list(Interval,L1,L),
 8302	intervals_to_list(Intervals,L,L2).
 8303
 8304% converts an interval into a list
 8305interval_to_list(Start-Finish,[]):-
 8306	Start > Finish, !.
 8307interval_to_list(Start-Finish,[Start|T]):-
 8308	Start1 is Start+1,
 8309	interval_to_list(Start1-Finish,T).
 8310
 8311% converts an interval into a list
 8312%	with an accumulator list. Result will be in reverse order
 8313interval_to_list(Start-Finish,L,L):-
 8314	Start > Finish, !.
 8315interval_to_list(Start-Finish,L,L1):-
 8316	Start1 is Start+1,
 8317	interval_to_list(Start1-Finish,[Start|L],L1).
 8318
 8319% interval_subsumes(+I1,+I2)
 8320%	checks to see if interval I1 subsumes I2
 8321interval_subsumes(Start1-Finish1,Start2-Finish2):-
 8322	Start1 =< Start2,
 8323	Finish1 >= Finish2.
 8324
 8325interval_subtract(Start1-Finish1,Start1-Finish1,[]):- !.
 8326interval_subtract(Start1-Finish1,Start1-Finish2,[S2-Finish1]):-
 8327	!,
 8328	S2 is Finish2 + 1.
 8329interval_subtract(Start1-Finish1,Start2-Finish1,[Start1-S1]):-
 8330	!,
 8331	S1 is Start2 - 1.
 8332interval_subtract(Start1-Finish1,Start2-Finish2,[Start1-S1,S2-Finish1]):-
 8333	S1 is Start2 - 1,
 8334	S2 is Finish2 + 1,
 8335	S1 >= Start1, Finish1 >= S2, !.
 8336
 8337
 8338% code for set manipulation utilities 
 8339% taken from the Yap library
 8340% aleph_ord_subtract(+Set1,+Set2,?Difference)
 8341% is true when Difference contains all and only the elements of Set1
 8342% which are not also in Set2.
 8343aleph_ord_subtract(Set1,[],Set1) :- !.
 8344aleph_ord_subtract([],_,[]) :- !.
 8345aleph_ord_subtract([Head1|Tail1],[Head2|Tail2],Difference) :-
 8346        compare(Order,Head1,Head2),
 8347        aleph_ord_subtract(Order,Head1,Tail1,Head2,Tail2,Difference).
 8348
 8349aleph_ord_subtract(=,_,    Tail1,_,    Tail2,Difference) :-
 8350	aleph_ord_subtract(Tail1,Tail2,Difference).
 8351aleph_ord_subtract(<,Head1,Tail1,Head2,Tail2,[Head1|Difference]) :-
 8352        aleph_ord_subtract(Tail1,[Head2|Tail2],Difference).
 8353aleph_ord_subtract(>,Head1,Tail1,_,    Tail2,Difference) :-
 8354        aleph_ord_subtract([Head1|Tail1],Tail2,Difference). 
 8355
 8356% aleph_ord_disjoint(+Set1,+Set2)
 8357% is true when the two ordered sets have no element in common.  If the
 8358% arguments are not ordered,I have no idea what happens.
 8359aleph_ord_disjoint([],_) :- !.
 8360aleph_ord_disjoint(_,[]) :- !.
 8361aleph_ord_disjoint([Head1|Tail1],[Head2|Tail2]) :-
 8362        compare(Order,Head1,Head2),
 8363        aleph_ord_disjoint(Order,Head1,Tail1,Head2,Tail2).
 8364
 8365aleph_ord_disjoint(<,_,Tail1,Head2,Tail2) :-
 8366        aleph_ord_disjoint(Tail1,[Head2|Tail2]).
 8367aleph_ord_disjoint(>,Head1,Tail1,_,Tail2) :-
 8368        aleph_ord_disjoint([Head1|Tail1],Tail2).
 8369
 8370
 8371% aleph_ord_union(+Set1,+Set2,?Union)
 8372% is true when Union is the union of Set1 and Set2.  Note that when
 8373% something occurs in both sets,we want to retain only one copy.
 8374aleph_ord_union(Set1,[],Set1) :- !.
 8375aleph_ord_union([],Set2,Set2) :- !.
 8376aleph_ord_union([Head1|Tail1],[Head2|Tail2],Union) :-
 8377        compare(Order,Head1,Head2),
 8378        aleph_ord_union(Order,Head1,Tail1,Head2,Tail2,Union).
 8379
 8380aleph_ord_union(=,Head, Tail1,_,    Tail2,[Head|Union]) :-
 8381        aleph_ord_union(Tail1,Tail2,Union).
 8382aleph_ord_union(<,Head1,Tail1,Head2,Tail2,[Head1|Union]) :-
 8383        aleph_ord_union(Tail1,[Head2|Tail2],Union).
 8384aleph_ord_union(>,Head1,Tail1,Head2,Tail2,[Head2|Union]) :-
 8385        aleph_ord_union([Head1|Tail1],Tail2,Union).
 8386
 8387% aleph_ord_union(+Set1,+Set2,?Union,?Difference)
 8388% is true when Union is the union of Set1 and Set2 and Difference is the
 8389% difference between Set2 and Set1.
 8390aleph_ord_union(Set1,[],Set1,[]) :- !.
 8391aleph_ord_union([],Set2,Set2,Set2) :- !.
 8392aleph_ord_union([Head1|Tail1],[Head2|Tail2],Union,Diff) :-
 8393        compare(Order,Head1,Head2),
 8394        aleph_ord_union(Order,Head1,Tail1,Head2,Tail2,Union,Diff).
 8395
 8396aleph_ord_union(=,Head, Tail1,_, Tail2,[Head|Union],Diff) :-
 8397        aleph_ord_union(Tail1,Tail2,Union,Diff).
 8398aleph_ord_union(<,Head1,Tail1,Head2,Tail2,[Head1|Union],Diff) :-
 8399        aleph_ord_union(Tail1,[Head2|Tail2],Union,Diff).
 8400aleph_ord_union(>,Head1,Tail1,Head2,Tail2,[Head2|Union],[Head2|Diff]) :-
 8401        aleph_ord_union([Head1|Tail1],Tail2,Union,Diff).
 8402
 8403aleph_ord_intersection(_,[],[]) :- !.
 8404aleph_ord_intersection([],_,[]) :- !.
 8405aleph_ord_intersection([Head1|Tail1],[Head2|Tail2],Intersection) :-
 8406        compare(Order,Head1,Head2),
 8407        aleph_ord_intersection(Order,Head1,Tail1,Head2,Tail2,Intersection).
 8408
 8409aleph_ord_intersection(=,Head,Tail1,_,Tail2,[Head|Intersection]) :-
 8410        aleph_ord_intersection(Tail1,Tail2,Intersection).
 8411aleph_ord_intersection(<,_,Tail1,Head2,Tail2,Intersection) :-
 8412        aleph_ord_intersection(Tail1,[Head2|Tail2],Intersection).
 8413aleph_ord_intersection(>,Head1,Tail1,_,Tail2,Intersection) :-
 8414        aleph_ord_intersection([Head1|Tail1],Tail2,Intersection).
 8415
 8416aleph_ord_subset([], _) :- !.
 8417aleph_ord_subset([Head1|Tail1], [Head2|Tail2]) :-
 8418        compare(Order, Head1, Head2),
 8419        aleph_ord_subset(Order, Head1, Tail1, Head2, Tail2).
 8420
 8421aleph_ord_subset(=, _, Tail1, _, Tail2) :-
 8422        aleph_ord_subset(Tail1, Tail2).
 8423aleph_ord_subset(>, Head1, Tail1, _, Tail2) :-
 8424        aleph_ord_subset([Head1|Tail1], Tail2).
 8425
 8426vars_in_term([],Vars,Vars1):- sort(Vars,Vars1), !.
 8427vars_in_term([Var|T],VarsSoFar,Vars):-
 8428        var(Var), !,
 8429        vars_in_term(T,[Var|VarsSoFar],Vars).
 8430vars_in_term([Term|T],VarsSoFar,Vars):-
 8431        Term =.. [_|Terms], !,
 8432        vars_in_term(Terms,VarsSoFar,V1),
 8433        vars_in_term(T,V1,Vars).
 8434vars_in_term([_|T],VarsSoFar,Vars):-
 8435        vars_in_term(T,VarsSoFar,Vars).
 8436
 8437occurs_in(Vars,(Lit,_)):-
 8438	occurs_in(Vars,Lit), !.
 8439occurs_in(Vars,(_,Lits)):-
 8440	!,
 8441	occurs_in(Vars,Lits).
 8442occurs_in(Vars,Lit):-
 8443	functor(Lit,_,Arity),
 8444	occurs1(Vars,Lit,1,Arity).
 8445
 8446occurs1(Vars,Lit,Argno,MaxArgs):- 
 8447	Argno =< MaxArgs,
 8448	arg(Argno,Lit,Term),
 8449	vars_in_term([Term],[],Vars1),
 8450	aleph_member(X,Vars), aleph_member(Y,Vars1), 
 8451	X == Y, !.
 8452occurs1(Vars,Lit,Argno,MaxArgs):- 
 8453	Argno < MaxArgs,
 8454	Next is Argno + 1,
 8455	occurs1(Vars,Lit,Next,MaxArgs).
 8456
 8457
 8458declare_dynamic(Name/Arity,M):-
 8459	M:dynamic(Name/Arity).
 8460
 8461aleph_abolish(Name/Arity,M):-
 8462	functor(Pred,Name,Arity),
 8463	(predicate_property(M:Pred,dynamic) ->
 8464		retractall(M:Pred);
 8465		abolish(M:Name/Arity)).
 8466% AXO: Tolto perché infastidisce e non serve
 8467aleph_open(File,read,Stream):-
 8468	!,
 8469	(exists(File) ->
 8470		open(File,read,Stream);
 8471		fail).
 8472aleph_open(File,Mode,Stream):-
 8473	open(File,Mode,Stream).
 8474
 8475clean_up(M):-
 8476        clean_up_init(M),
 8477        clean_up_sat(M),
 8478        clean_up_reduce(M).
 8479
 8480clean_up_init(M):-
 8481	aleph_abolish('$aleph_good'/3,M),
 8482	retractall(M:'$aleph_search'(last_good,_)),
 8483	aleph_abolish('$aleph_feature'/2,M).
 8484	
 8485
 8486clean_up_sat(M):-
 8487	aleph_abolish('$aleph_sat'/2,M),
 8488	aleph_abolish('$aleph_local'/2,M),
 8489	aleph_abolish('$aleph_sat_atom'/2,M),
 8490	aleph_abolish('$aleph_sat_ovars'/2,M),
 8491	aleph_abolish('$aleph_sat_ivars'/2,M),
 8492	aleph_abolish('$aleph_sat_varscopy'/3,M),
 8493	aleph_abolish('$aleph_sat_varequiv'/3,M),
 8494	aleph_abolish('$aleph_sat_terms'/4,M),
 8495	aleph_abolish('$aleph_sat_vars'/4,M),
 8496	aleph_abolish('$aleph_sat_litinfo'/6,M),
 8497	retractall(M:'$aleph_search'(pclause,_)),
 8498	garbage_collect.
 8499
 8500clean_up_reduce(M):-
 8501	aleph_abolish('$aleph_local'/2,M),
 8502	clean_up_search(M),
 8503	retractall(M:'$aleph_search'(pclause,_)),
 8504	garbage_collect.
 8505
 8506clean_up_search(M):-
 8507	retractall(M:'$aleph_search'(bad,_)),
 8508	retractall(M:'$aleph_search'(best,_)),
 8509	retractall(M:'$aleph_search'(best_label,_)),
 8510	retractall(M:'$aleph_search'(clauseprior,_)),
 8511	retractall(M:'$aleph_search'(covers,_)),
 8512	retractall(M:'$aleph_search'(coversn,_)),
 8513	retractall(M:'$aleph_search'(current,_)),
 8514	retractall(M:'$aleph_search'(label,_)),
 8515	retractall(M:'$aleph_search'(modes,_)),
 8516	retractall(M:'$aleph_search'(nextnode,_)),
 8517	retractall(M:'$aleph_search'(openlist,_)),
 8518	retractall(M:'$aleph_search'(pclause,_)),
 8519	retractall(M:'$aleph_search'(selected,_)),
 8520	retractall(M:'$aleph_search_seen'(_,_)),
 8521	retractall(M:'$aleph_search_expansion'(_,_,_,_)),
 8522	retractall(M:'$aleph_search_gain'(_,_,_,_)),
 8523	retractall(M:'$aleph_search_node'(_,_,_,_,_,_,_,_)).
 8524
 8525
 8526clean_up_examples(M):-
 8527	clean_up_examples(pos,M),
 8528	clean_up_examples(neg,M),
 8529	clean_up_examples(rand,M).
 8530
 8531clean_up_tre(M):-
 8532	retractall(M:'$aleph_search'(tree,_)),
 8533	retractall(M:'$aleph_search'(tree_startdistribution,_)),
 8534	retractall(M:'$aleph_search'(tree_leaf,_)),
 8535	retractall(M:'$aleph_search'(tree_lastleaf,_)),
 8536	retractall(M:'$aleph_search'(tree_newleaf,_)),
 8537	retractall(M:'$aleph_search'(tree_besterror,_)),
 8538	retractall(M:'$aleph_search'(tree_gain,_)).
 8539
 8540clean_up_examples(Type,M):-
 8541	retractall(M:'$aleph_global'(size,size(Type,_))),
 8542	retractall(M:'$aleph_global'(atoms,atoms(Type,_))),
 8543	retractall(M:'$aleph_global'(atoms_left,atoms_left(Type,_))),
 8544	retractall(M:'$aleph_global'(last_example,last_example(Type,_))).
 8545
 8546clean_up_hypothesis(M):-
 8547        retractall(M:'$aleph_global'(hypothesis,hypothesis(_,_,_,_))).
 8548
 8549depth_bound_call(G,M):-
 8550	M:'$aleph_global'(depth,set(depth,D)),
 8551	call_with_depth_bound(G,D,M).
 8552
 8553call_with_depth_bound((H:-B),D,M):-
 8554	!,
 8555	call_with_depth_bound((H,B),D,M).
 8556call_with_depth_bound((A,B),D,M):-
 8557	!,
 8558	depth_bound_call(A,D,M),
 8559	call_with_depth_bound(B,D,M).
 8560call_with_depth_bound(A,D,M):-
 8561	depth_bound_call(A,D,M).
 8562
 8563binom_lte(_,_,O,0.0):- O < 0, !.
 8564binom_lte(N,P,O,Prob):-
 8565        binom(N,P,O,Prob1),
 8566        O1 is O - 1,
 8567        binom_lte(N,P,O1,Prob2),
 8568        Prob is Prob1 + Prob2, !.
 8569
 8570binom(N,_,O,0.0):- O > N, !.
 8571binom(N,P,O,Prob):-
 8572        aleph_choose(N,O,C),
 8573        E1 is P^O,
 8574        P2 is 1 - P,
 8575        O2 is N - O,
 8576        E2 is P2^O2,
 8577        Prob is C*E1*E2, !.
 8578 
 8579aleph_choose(N,I,V):-
 8580        NI is N-I,
 8581        (NI > I -> pfac(N,NI,I,V) ; pfac(N,I,NI,V)).
 8582
 8583pfac(0,_,_,1).
 8584pfac(1,_,_,1).
 8585pfac(N,N,_,1).
 8586pfac(N,I,C,F):-
 8587        N1 is N-1,
 8588        C1 is C-1,
 8589        pfac(N1,I,C1,N1F),
 8590        F1 is N/C,
 8591        F is N1F*F1.
 8592
 8593% record_example(+Check,+Type,+Example,-N)
 8594%	records Example of type Type
 8595%	if Check = check, then checks to see if example exists
 8596%		also updates number of related databases accordingly
 8597%	if Check = nocheck then no check is done
 8598%	returns example number N and Flag
 8599%	if Flag = new then example is a new example of Type
 8600record_example(check,Type,Example,N1,M):- 
 8601	(once(M:example(N1,Type,Example)) -> true;
 8602		record_example(nocheck,Type,Example,N1,M),
 8603		(retract(M:'$aleph_global'(atoms,atoms(Type,Atoms))) ->
 8604				true;
 8605				Atoms = []),
 8606		(retract(M:'$aleph_global'(atoms_left,atoms_left(Type,AtomsLeft)))->
 8607				true;
 8608				AtomsLeft = []),
 8609		(retract(M:'$aleph_global'(last_example,last_example(Type,_))) ->
 8610				true;
 8611				true),
 8612		update(Atoms,N1-N1,NewAtoms),
 8613		update(AtomsLeft,N1-N1,NewAtomsLeft),
 8614		asserta(M:'$aleph_global'(atoms,atoms(Type,NewAtoms))),
 8615		asserta(M:'$aleph_global'(atoms_left,atoms_left(Type,
 8616						NewAtomsLeft))),
 8617		asserta(M:'$aleph_global'(last_example,last_example(Type,N1)))),
 8618	!.
 8619record_example(nocheck,Type,Example,N1,M):-
 8620	(retract(M:'$aleph_global'(size,size(Type,N)))->
 8621		true;
 8622		N is 0),
 8623	N1 is N + 1,
 8624	asserta(M:'$aleph_global'(size,size(Type,N1))),
 8625	(Type \= neg ->
 8626		setting(skolemvars,Sk1,M),
 8627		skolemize(Example,Fact,Body,Sk1,SkolemVars),
 8628		record_skolemized(Type,N1,SkolemVars,Fact,Body,M),
 8629		(Sk1 = SkolemVars -> true;
 8630			set(skolemvars,SkolemVars,M));
 8631		split_clause(Example,Head,Body),
 8632		record_nskolemized(Type,N1,Head,Body,M)), !.
 8633
 8634
 8635record_targetpred(M):-
 8636	retract(M:'$aleph_local'(backpred,Name/Arity)),
 8637	once(M:'$aleph_global'(determination,determination(Name/Arity,_))),
 8638	asserta(M:'$aleph_global'(targetpred,targetpred(Name/Arity))),
 8639	record_testclause(Name/Arity,M),
 8640	fail.
 8641record_targetpred(_M).
 8642
 8643check_recursive_calls(M):-
 8644	M:'$aleph_global'(targetpred,targetpred(Name/Arity)),
 8645	M:'$aleph_global'(determination,determination(Name/Arity,Name/Arity)),
 8646	record_recursive_sat_call(Name/Arity,M),
 8647	set(recursion,true,M),
 8648	fail.
 8649check_recursive_calls(_M).
 8650
 8651check_posonly(M):-
 8652	M:'$aleph_global'(size,size(rand,N)), 
 8653	N > 0, !.
 8654check_posonly(M):-
 8655	setting(evalfn,posonly,M),
 8656	\+(M:'$aleph_global'(modeh,modeh(_,_))),
 8657	p1_message('error'),
 8658	p_message('missing modeh declaration in posonly mode'), !,
 8659	fail.
 8660check_posonly(M):-
 8661	retractall(M:'$aleph_global'(slp_count,_,_)),
 8662	retractall(M:'$aleph_local'(slp_sample,_)),
 8663	retractall(M:'$aleph_local'(slp_samplenum,_)),
 8664	setting(evalfn,posonly,M),
 8665	setting(gsamplesize,S,M),
 8666	condition_target(M),
 8667	M:'$aleph_global'(targetpred,targetpred(Name/Arity)),
 8668	gsample(Name/Arity,S,M), !.
 8669check_posonly(_M).
 8670
 8671check_prune_defs(M):-
 8672	clause(M:prune(_),_), !,
 8673	set(prune_defs,true,M).
 8674check_prune_defs(_M).
 8675
 8676check_auto_refine(M):-
 8677	(setting(construct_bottom,reduction,M);setting(construct_bottom,false,M)),
 8678	\+(setting(autorefine,true,M)), !,
 8679	(setting(refine,user,M) -> true; set(refine,auto,M)).
 8680check_auto_refine(_M).
 8681
 8682check_user_search(M):-
 8683	setting(evalfn,user,M),
 8684	\+(cost_cover_required(M)),
 8685	set(lazy_on_cost,true,M), !.
 8686check_user_search(_M).
 8687
 8688check_abducibles(M):-
 8689	M:'$aleph_global'(abducible,abducible(Name/Arity)),
 8690	record_testclause(Name/Arity,M),
 8691	record_abclause(Name/Arity,M),
 8692	fail.
 8693check_abducibles(_M).
 8694
 8695cost_cover_required(M):-
 8696	clause(M:cost(_,Label,Cost),Body),
 8697	vars_in_term([Label],[],Vars),
 8698	(occurs_in(Vars,p(Cost)); occurs_in(Vars,Body)), !.
 8699
 8700set_lazy_recalls(M):-
 8701	M:'$aleph_global'(lazy_evaluate,lazy_evaluate(Name/Arity)),
 8702	functor(Pred,Name,Arity),
 8703	% asserta('$aleph_global'(lazy_recall,lazy_recall(Name/Arity,1))),
 8704	asserta(M:'$aleph_global'(lazy_recall,lazy_recall(Name/Arity,0))),
 8705	M:'$aleph_global'(mode,mode(Recall,Pred)),
 8706	M:'$aleph_global'(lazy_recall,lazy_recall(Name/Arity,N)),
 8707	(Recall = '*' -> RecallNum = 100; RecallNum = Recall),
 8708	RecallNum > N,
 8709	retract(M:'$aleph_global'(lazy_recall,lazy_recall(Name/Arity,N))),
 8710	asserta(M:'$aleph_global'(lazy_recall,lazy_recall(Name/Arity,RecallNum))),
 8711	fail.
 8712set_lazy_recalls(_M).
 8713
 8714set_lazy_on_contradiction(_,_,M):-
 8715	M:'$aleph_global'(lazy_on_contradiction,set(lazy_on_contradiction,false)), !.
 8716set_lazy_on_contradiction(P,N,M):-
 8717	Tot is P + N,
 8718	Tot >= 100, !,
 8719	set(lazy_on_contradiction,true,M).
 8720set_lazy_on_contradiction(_,_,_M).
 8721
 8722% The "pclause" trick: much more effective with the use of recorded/3
 8723% clause for testing partial clauses obtained in search
 8724% only needed when learning recursive theories or
 8725% proof_strategy is not restricted_sld.
 8726record_testclause(Name/Arity,M):-
 8727        functor(Head,Name,Arity),
 8728        Clause = (Head:-
 8729                        '$aleph_search'(pclause,pclause(Head,Body)),
 8730                        Body, !),
 8731        assertz(M:Clause).
 8732
 8733% The "pclause" trick for abducible predicates
 8734record_abclause(Name/Arity,M):-
 8735        functor(Head,Name,Arity),
 8736        Clause = (Head:-
 8737                        '$aleph_search'(abduced,pclause(Head,Body)),
 8738                        Body, !),
 8739        assertz(M:Clause).
 8740
 8741% clause for incorporating recursive calls into bottom clause
 8742% this is done by allowing calls to the positive examples
 8743record_recursive_sat_call(Name/Arity,M):-
 8744        functor(Head,Name,Arity),
 8745	Clause = (Head:-
 8746			'$aleph_global'(stage,set(stage,saturation)),
 8747			'$aleph_sat'(example,example(Num,Type)),
 8748			example(Num1,Type,Head),
 8749			Num1 \= Num, !),	% to prevent tautologies
 8750	assertz(M:Clause).
 8751
 8752skolemize((Head:-Body),SHead,SBody,Start,SkolemVars):-
 8753	!,
 8754	copy_term((Head:-Body),(SHead:-Body1)),
 8755	numbervars((SHead:-Body1),Start,SkolemVars),
 8756	goals_to_list(Body1,SBody).
 8757skolemize(UnitClause,Lit,[],Start,SkolemVars):-
 8758	copy_term(UnitClause,Lit),
 8759	numbervars(Lit,Start,SkolemVars).
 8760skolemize(UnitClause,Lit):-
 8761	skolemize(UnitClause,Lit,[],0,_).
 8762
 8763record_nskolemized(Type,N1,Head,true,M):-
 8764	!,
 8765	assertz(M:example(N1,Type,Head)).
 8766record_nskolemized(Type,N1,Head,Body,M):-
 8767	assertz(M:(example(N1,Type,Head):-Body)).
 8768
 8769record_skolemized(Type,N1,SkolemVars,Head,Body,M):-
 8770	assertz(M:example(N1,Type,Head)),
 8771        functor(Head,Name,Arity),
 8772        update_backpreds(Name/Arity,M),
 8773	add_backs(Body,M),
 8774	add_skolem_types(SkolemVars,Head,Body,M).
 8775
 8776add_backs([],_M).
 8777add_backs([Lit|Lits],M):-
 8778	asserta(M:'$aleph_global'(back,back(Lit))),
 8779	functor(Lit,Name,Arity),
 8780	declare_dynamic(Name/Arity,M),
 8781	assertz(M:Lit),
 8782	add_backs(Lits,M).
 8783
 8784add_skolem_types(10000,_,_,_M):- !.	% no new skolem variables
 8785add_skolem_types(_,Head,Body,M):-
 8786	add_skolem_types([Head],M),
 8787	add_skolem_types(Body,M).
 8788
 8789add_skolem_types([],_M).
 8790add_skolem_types([Lit|Lits],M):-
 8791	functor(Lit,PSym,Arity),
 8792	get_modes(PSym/Arity,L,M),
 8793	add_skolem_types1(L,Lit,M),
 8794	add_skolem_types(Lits,M).
 8795
 8796add_skolem_types1([],_,_M).
 8797add_skolem_types1([Lit|Lits],Fact,M):-
 8798	split_args(Lit,_,I,O,C,M),
 8799	add_skolem_types2(I,Fact,M),
 8800	add_skolem_types2(O,Fact,M),
 8801	add_skolem_types2(C,Fact,M),
 8802	add_skolem_types1(Lits,Fact,M).
 8803
 8804add_skolem_types2([],_,_M).
 8805add_skolem_types2([Pos/Type|Rest],Literal,M):-
 8806	tparg(Pos,Literal,Arg),
 8807	SkolemType =.. [Type,Arg],
 8808	(M:'$aleph_global'(back,back(SkolemType))-> true;
 8809		asserta(M:'$aleph_global'(back,back(SkolemType))),
 8810		asserta(M:SkolemType)),
 8811	add_skolem_types2(Rest,Literal,M).
 8812
 8813
 8814copy_args(_,_,Arg,Arity):-
 8815	Arg > Arity, !.
 8816copy_args(Lit,Lit1,Arg,Arity):-
 8817	arg(Arg,Lit,T),
 8818	arg(Arg,Lit1,T),
 8819	NextArg is Arg + 1,
 8820	copy_args(Lit,Lit1,NextArg,Arity).
 8821
 8822copy_iargs(0,_,_,_):- !.
 8823copy_iargs(Arg,Old,New,Arg):-
 8824        !,
 8825        Arg1 is Arg - 1,
 8826        copy_iargs(Arg1,Old,New,Arg).
 8827copy_iargs(Arg,Old,New,Out):-
 8828        arg(Arg,Old,Val),
 8829        arg(Arg,New,Val),
 8830        Arg1 is Arg - 1,
 8831        copy_iargs(Arg1,Old,New,Out).
 8832
 8833
 8834index_clause((Head:-true),NextClause,(Head),M):-
 8835	!,
 8836	retract(M:'$aleph_global'(last_clause,last_clause(ClauseNum))),
 8837	NextClause is ClauseNum + 1,
 8838	asserta(M:'$aleph_global'(last_clause,last_clause(NextClause))).
 8839index_clause(Clause,NextClause,Clause,M):-
 8840	retract(M:'$aleph_global'(last_clause,last_clause(ClauseNum))),
 8841	NextClause is ClauseNum + 1,
 8842	asserta(M:'$aleph_global'(last_clause,last_clause(NextClause))).
 8843
 8844update_backpreds(Name/Arity,M):-
 8845	M:'$aleph_local'(backpred,Name/Arity), !.
 8846update_backpreds(Name/Arity,M):-
 8847	assertz(M:'$aleph_local'(backpred,Name/Arity)).
 8848	
 8849reset_counts(M):-
 8850	retractall(M:'$aleph_sat'(lastterm,_)),
 8851	retractall(M:'$aleph_sat'(lastvar,_)),
 8852	asserta(M:'$aleph_sat'(lastterm,0)),
 8853	asserta(M:'$aleph_sat'(lastvar,0)), !.
 8854
 8855% reset the number of successes for a literal: cut to avoid useless backtrack
 8856reset_succ(M):-
 8857        retractall(M:'$aleph_local'(last_success,_)),
 8858        asserta(M:'$aleph_local'(last_success,0)), !.
 8859
 8860skolem_var(Var,_M):-
 8861	atomic(Var), !,
 8862	name(Var,[36|_]).
 8863skolem_var(Var,M):-
 8864	gen_var(Num,M),
 8865	name(Num,L),
 8866	name(Var,[36|L]).
 8867
 8868gen_var(Var1,M):-
 8869	retract(M:'$aleph_sat'(lastvar,Var0)), !,
 8870        Var1 is Var0 + 1,
 8871	asserta(M:'$aleph_sat'(lastvar,Var1)).
 8872gen_var(0,M):-
 8873	asserta(M:'$aleph_sat'(lastvar,0)).
 8874
 8875copy_var(OldVar,NewVar,Depth,M):-
 8876	gen_var(NewVar,M),
 8877	M:'$aleph_sat_vars'(OldVar,TNo,_,_),
 8878	asserta(M:'$aleph_sat_vars'(NewVar,TNo,[],[])),
 8879	asserta(M:'$aleph_sat_varscopy'(NewVar,OldVar,Depth)).
 8880
 8881gen_litnum(Lit1,M):-
 8882	retract(M:'$aleph_sat'(lastlit,Lit0)), !,
 8883        Lit1 is Lit0 + 1,
 8884	asserta(M:'$aleph_sat'(lastlit,Lit1)).
 8885gen_litnum(0,M):-
 8886	asserta(M:'$aleph_sat'(lastlit,0)).
 8887
 8888gen_nlitnum(Lit1,M):-
 8889	retract(M:'$aleph_sat'(lastnlit,Lit0)), !,
 8890        Lit1 is Lit0 - 1,
 8891	asserta(M:'$aleph_sat'(lastnlit,Lit1)).
 8892gen_nlitnum(-1,M):-
 8893	asserta(M:'$aleph_sat'(lastnlit,-1)).
 8894
 8895% generate a new feature number
 8896% provided it is less than the maximum number of features allowed
 8897gen_featurenum(Feature1,M):-
 8898        M:'$aleph_feature'(last_feature,Feature0), !,
 8899        Feature1 is Feature0 + 1,
 8900	setting(max_features,FMax,M),
 8901	Feature1 =< FMax,
 8902        retract(M:'$aleph_feature'(last_feature,Feature0)), 
 8903        asserta(M:'$aleph_feature'(last_feature,Feature1)).
 8904gen_featurenum(1,M):-
 8905        asserta(M:'$aleph_feature'(last_feature,1)).
 8906
 8907gen_lits([],[],_M).
 8908gen_lits([Lit|Lits],[LitNum|Nums],M):-
 8909	gen_litnum(LitNum,M),
 8910	asserta(M:'$aleph_sat_litinfo'(LitNum,0,Lit,[],[],[])),
 8911	gen_lits(Lits,Nums,M).
 8912
 8913update_theory(ClauseIndex,M):-
 8914        retract(M:'$aleph_global'(hypothesis,hypothesis(OldLabel,Hypothesis,
 8915				OldPCover,OldNCover))), 
 8916	index_clause(Hypothesis,ClauseIndex,Clause,M),
 8917        (M:'$aleph_global'(example_selected,example_selected(_,Seed))-> true;
 8918                PCover = [Seed-_|_]),
 8919	(setting(lazy_on_cost,true,M) ->
 8920        	nlits(Clause,L),
 8921		label_create(Clause,Label,M),
 8922        	extract_pos(Label,PCover),
 8923        	extract_neg(Label,NCover),
 8924        	interval_count(PCover,PC),
 8925        	interval_count(NCover,NC),
 8926		setting(evalfn,Evalfn,M),
 8927		complete_label(Evalfn,Clause,[PC,NC,L],NewLabel,M),
 8928        	assertz(M:'$aleph_global'(theory,theory(ClauseIndex,
 8929					NewLabel/Seed,Clause,
 8930					PCover,NCover)));
 8931        	assertz(M:'$aleph_global'(theory,theory(ClauseIndex,
 8932					OldLabel/Seed,Clause,
 8933					OldPCover,OldNCover)))),
 8934	add_clause_to_background(ClauseIndex,M).
 8935
 8936add_clause_to_background(ClauseIndex,M):-
 8937        M:'$aleph_global'(theory,theory(ClauseIndex,Label/_,Clause,_,_)),
 8938	(setting(minpos,PMin,M) -> true; PMin = 1),
 8939	Label = [PC,_,_,F|_],
 8940	PC >= PMin,
 8941	setting(minscore,MinScore,M),
 8942	F >= MinScore, !,
 8943        (retract(M:'$aleph_global'(rules,rules(Rules)))->
 8944                asserta(M:'$aleph_global'(rules,rules([ClauseIndex|Rules])));
 8945                asserta(M:'$aleph_global'(rules,rules([ClauseIndex])))),
 8946	(setting(updateback,Update,M) -> true; Update = true),
 8947        (Update = true -> assertz(M:Clause); true),  !.
 8948add_clause_to_background(_,_M).
 8949
 8950
 8951rm_seeds(M):-
 8952	update_theory(ClauseIndex,M), !,
 8953	M:'$aleph_global'(theory,theory(ClauseIndex,_,_,PCover,NCover)),
 8954	rm_seeds(pos,PCover,M),
 8955	(setting(evalfn,posonly,M) -> rm_seeds(rand,NCover,M); true),
 8956	M:'$aleph_global'(atoms_left,atoms_left(pos,PLeft)),
 8957	interval_count(PLeft,PL),
 8958	p1_message('atoms left'), p_message(PL),
 8959	!.
 8960rm_seeds(_M).
 8961
 8962rm_seeds(pos,PCover,M):-
 8963	setting(construct_features,true,M),
 8964	setting(feature_construction,exhaustive,M), !,
 8965        retract(M:'$aleph_global'(atoms_left,atoms_left(pos,OldIntervals))),
 8966        (M:'$aleph_global'(example_selected,example_selected(_,Seed))-> true;
 8967                PCover = [Seed-_|_]),
 8968        rm_seeds1([Seed-Seed],OldIntervals,NewIntervals),
 8969        assertz(M:'$aleph_global'(atoms_left,atoms_left(pos,NewIntervals))).
 8970rm_seeds(Type,RmIntervals,M) :-
 8971        retract(M:'$aleph_global'(atoms_left,atoms_left(Type,OldIntervals))),
 8972        rm_seeds1(RmIntervals,OldIntervals,NewIntervals),
 8973        assertz(M:'$aleph_global'(atoms_left,atoms_left(Type,NewIntervals))).
 8974 
 8975rm_seeds1([],Done,Done).
 8976rm_seeds1([Start-Finish|Rest],OldIntervals,NewIntervals) :-
 8977        rm_interval(Start-Finish,OldIntervals,MidIntervals),!,
 8978        rm_seeds1(Rest,MidIntervals,NewIntervals).
 8979
 8980% update lower estimate on maximum size cover set for an atom
 8981update_coverset(Type,_,M):-
 8982        M:'$aleph_global'(hypothesis,hypothesis(Label,_,PCover,_)),
 8983	Label = [_,_,_,GainE|_],
 8984	arithmetic_expression_value(GainE,Gain),
 8985        worse_coversets(PCover,Type,Gain,Worse,M),
 8986        (Worse = [] -> true;
 8987                update_theory(NewClause,M),
 8988                update_coversets(Worse,NewClause,Type,Label,M)).
 8989
 8990% revise coversets of previous atoms
 8991worse_coversets(_,_,_,[],M):-
 8992	\+(M:'$aleph_global'(maxcover,set(maxcover,true))), !.
 8993worse_coversets([],_,_,[],_M).
 8994worse_coversets([Interval|Intervals],Type,Gain,Worse,M):-
 8995	worse_coversets1(Interval,Type,Gain,W1,M),
 8996	worse_coversets(Intervals,Type,Gain,W2,M),
 8997	aleph_append(W2,W1,Worse), !.
 8998
 8999worse_coversets1(Start-Finish,_,_,[],_M):-
 9000        Start > Finish, !.
 9001worse_coversets1(Start-Finish,Type,Gain,Rest,M):-
 9002        M:'$aleph_global'(max_set,max_set(Type,Start,Label1,_)),
 9003	Label1 = [_,_,_,Gain1E|_],
 9004	arithmetic_expression_value(Gain1E,Gain1),
 9005        Gain1 >= Gain, !,
 9006        Next is Start + 1,
 9007        worse_coversets1(Next-Finish,Type,Gain,Rest,M), !.
 9008worse_coversets1(Start-Finish,Type,Gain,[Start|Rest],M):-
 9009        Next is Start + 1,
 9010        worse_coversets1(Next-Finish,Type,Gain,Rest,M), !.
 9011
 9012update_coversets([],_,_,_,_M).
 9013update_coversets([Atom|Atoms],ClauseNum,Type,Label,M):-
 9014	(retract(M:'$aleph_global'(max_set,max_set(Type,Atom,_,_)))->
 9015		true;
 9016		true),
 9017	asserta(M:'$aleph_global'(max_set,max_set(Type,Atom,Label,ClauseNum))),
 9018	update_coversets(Atoms,ClauseNum,Type,Label,M), !.
 9019
 9020rm_intervals([],I,I).
 9021rm_intervals([I1|I],Intervals,Result):-
 9022	rm_interval(I1,Intervals,Intervals1), 
 9023	rm_intervals(I,Intervals1,Result), !.
 9024
 9025rm_interval(_,[],[]).
 9026rm_interval(I1,[Interval|Rest],Intervals):-
 9027	interval_intersection(I1,Interval,I2), !,
 9028	interval_subtract(Interval,I2,I3),
 9029	rm_interval(I1,Rest,I4),
 9030	aleph_append(I4,I3,Intervals).
 9031rm_interval(I1,[Interval|Rest],[Interval|Intervals]):-
 9032	rm_interval(I1,Rest,Intervals).
 9033
 9034% gen_sample(+Type,+N,M)
 9035% select N random samples from the set of examples uncovered. Type is one of pos/neg
 9036% if N = 0 returns first example in Set
 9037% resamples the same example R times where set(resample,R)
 9038gen_sample(Type,0,M):-
 9039	!,
 9040	M:'$aleph_global'(atoms_left,atoms_left(Type,[ExampleNum-_|_])),
 9041	retractall(M:'$aleph_global'(example_selected,example_selected(_,_))),
 9042	p1_message('select example'), p_message(ExampleNum),
 9043	(setting(resample,Resample,M) -> true; Resample = 1),
 9044	gen_sample(Resample,Type,ExampleNum,M).
 9045gen_sample(Type,SampleSize,M):-
 9046	M:'$aleph_global'(atoms_left,atoms_left(Type,Intervals)),
 9047	% p1_message('select from'), p_message(Intervals),
 9048	interval_count(Intervals,AtomsLeft),
 9049	N is min(AtomsLeft,SampleSize),
 9050	assertz(M:'$aleph_local'(sample_num,0)),
 9051	retractall(M:'$aleph_global'(example_selected,example_selected(_,_))),
 9052	(setting(resample,Resample,M) -> true; Resample = 1),
 9053	repeat,
 9054	M:'$aleph_local'(sample_num,S1),
 9055	S is S1 + 1,
 9056	(S =< N ->
 9057		get_random(AtomsLeft,INum),
 9058		select_example(INum,0,Intervals,ExampleNum),
 9059		\+(M:'$aleph_global'(example_selected,
 9060				example_selected(Type,ExampleNum))),
 9061		p1_message('select example'), p_message(ExampleNum),
 9062		retract(M:'$aleph_local'(sample_num,S1)),
 9063		assertz(M:'$aleph_local'(sample_num,S)),
 9064		gen_sample(Resample,Type,ExampleNum,M),
 9065		fail;
 9066		retract(M:'$aleph_local'(sample_num,S1))), !.
 9067
 9068gen_sample(0,_,_,_M):- !.
 9069gen_sample(R,Type,ExampleNum,M):-
 9070	assertz(M:'$aleph_global'(example_selected,
 9071			example_selected(Type,ExampleNum))),
 9072	R1 is R - 1,
 9073	gen_sample(R1,Type,ExampleNum,M).
 9074
 9075select_example(Num,NumberSoFar,[Start-Finish|_],ExampleNum):-
 9076	Num =< NumberSoFar + Finish - Start + 1, !,
 9077	ExampleNum is Num - NumberSoFar + Start - 1.
 9078select_example(Num,NumberSoFar,[Start-Finish|Rest],ExampleNum):-
 9079	N1 is NumberSoFar + Finish - Start + 1,
 9080	select_example(Num,N1,Rest,ExampleNum).
 9081
 9082% get_random(+Last,-Num)
 9083% 	get a random integer between 1 and Last
 9084get_random(Last,INum):-
 9085	aleph_random(X),
 9086	INum1 is integer(X*Last + 0.5),
 9087	(INum1 = 0 ->
 9088		INum = 1;
 9089		(INum1 > Last ->
 9090			INum = Last;
 9091			INum = INum1
 9092		)
 9093	).
 9094
 9095% get_rrandom(+Last,-Num)
 9096% 	get a random floating point number between 1 and Last
 9097get_rrandom(Last,Num):-
 9098	aleph_random(X),
 9099	Num is X*Last.
 9100
 9101% distrib(+Interval,+Prob,-Distrib)
 9102%	generate discrete distribution Distrib
 9103%	by assigning all elements in Interval the probability Prob
 9104distrib(X-Y,_,[]):-  X > Y, !.
 9105distrib(X-Y,P,[P-X|D]):-
 9106	X1 is X + 1,
 9107	distrib(X1-Y,P,D).
 9108
 9109% draw_element(+D,-E)
 9110%	draw element E using distribution D
 9111%	D is a list specifying the probability of each element E
 9112%		in the form p1-e1, p2-e2, ... ,pn-en
 9113%	       	proportions pi are normalised to add to 1
 9114draw_element(D,E):-
 9115	normalise_distribution(D,Distr),
 9116	aleph_random(X),
 9117	draw_element(Distr,0,X,E).
 9118
 9119draw_element([P1-E1|T],CumProb,X,E):-
 9120	CumProb1 is CumProb + P1,
 9121	(X =< CumProb1 -> E = E1;
 9122		draw_element(T,CumProb1,X,E)).
 9123
 9124normalise_distribution(D,Distr):-
 9125	key_sum(D,Sum),
 9126	(0.0 is float(Sum) -> Distr = D;
 9127		normalise_distribution(D,Sum,D1),
 9128		keysort(D1,Distr)).
 9129
 9130key_sum([],0.0).
 9131key_sum([K1-_|T],Sum):-
 9132	key_sum(T,S1),
 9133	Sum is float(K1 + S1).
 9134
 9135normalise_distribution([],_,[]).
 9136normalise_distribution([K1-X1|T],Sum,[K2-X1|T1]):-
 9137	K2 is K1/Sum,
 9138	normalise_distribution(T,Sum,T1).
 9139
 9140% random_select(-Num,+List1,-List2)
 9141%       randomly remove an element Num from List1 to give List2
 9142random_select(X,[X],[]):- !.
 9143random_select(X,L,Left):-
 9144        length(L,N),
 9145        N > 0,
 9146        get_random(N,I),
 9147        aleph_remove_nth(I,L,X,Left).
 9148
 9149% random_nselect(+Num,+List1,-List2)
 9150%       randomly remove Num elements from List1 to give List2
 9151random_nselect(0,_,[]):- !.
 9152random_nselect(_,[],[]):- !.
 9153random_nselect(N,List1,[X|List2]):-
 9154        random_select(X,List1,Left),
 9155        N1 is N - 1,
 9156        random_nselect(N1,Left,List2).
 9157
 9158% random_select_from_intervals(-Num,+IList)
 9159% 	randomly select an element from an interval list
 9160random_select_from_intervals(N,IList):-
 9161	interval_count(IList,L),
 9162	get_random(L,X),
 9163	interval_select(X,IList,N).
 9164
 9165
 9166normal(Mean,Sigma,X):-
 9167	std_normal(X1),
 9168	X is Mean + Sigma*X1.
 9169
 9170get_normal(0,_,_,[]):- !.
 9171get_normal(N,Mean,Sigma,[X|Xs]):-
 9172        N > 0,
 9173        normal(Mean,Sigma,X),
 9174        N1 is N - 1,
 9175        get_normal(N1,Mean,Sigma,Xs).
 9176
 9177% Polar method for generating random variates
 9178% from a standard normal distribution.
 9179% From A.M. Law and W.D. Kelton, "Simulation Modeling and Analysis",
 9180% 	McGraw-Hill,2000
 9181std_normal(X):-
 9182	aleph_random(U1),
 9183	aleph_random(U2),
 9184	V1 is 2*U1 - 1,
 9185	V2 is 2*U2 - 1,
 9186	W is V1^2 + V2^2,
 9187	(W > 1 -> std_normal(X);
 9188		Y is sqrt((-2.0*log(W))/W),
 9189		X is V1*Y).
 9190
 9191% Approximate method for computing the chi-square value
 9192% given the d.f. and probability (to the right). Uses
 9193% a normal approximation and Monte-Carlo simulation.
 9194% The normal approximation used is the one proposed by
 9195% E.B. Wilson and M.M. Hilferty (1931). "The distribution of chi-square"
 9196%  	PNAS, 17, 684.
 9197% Monte-Carlo simulation uses 1000 trials.
 9198chi_square(DF,Prob,ChisqVal):-
 9199	DF > 0,
 9200	Mean is 1 - 2/(9*DF),
 9201	Sigma is sqrt(2/(9*DF)),
 9202	NTrials is 1000,
 9203	get_normal(NTrials,Mean,Sigma,X),
 9204	sort(X,Z),
 9205	ProbLeft is 1.0 - Prob,
 9206	Index is integer(ProbLeft*NTrials),
 9207	(Index > NTrials ->
 9208		aleph_remove_nth(NTrials,Z,Val,_);
 9209		aleph_remove_nth(Index,Z,Val,_)),
 9210	ChisqVal is DF*(Val^3).
 9211
 9212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 9213% L A B E L S   A N D    E V A L F N S
 9214% 
 9215
 9216label_create(Clause,Label,M):-
 9217        M:'$aleph_global'(last_example,last_example(pos,Last1)),
 9218	Type1 = pos,
 9219	(setting(evalfn,posonly,M) ->
 9220        	M:'$aleph_global'(last_example,last_example(rand,Last2)),
 9221		Type2 = rand;
 9222        	M:'$aleph_global'(last_example,last_example(neg,Last2)),
 9223		Type2 = neg),
 9224	label_create(Clause,Type1,[1-Last1],Type2,[1-Last2],Label,M).
 9225
 9226label_create(Type,Clause,Label,M):-
 9227        M:'$aleph_global'(last_example,last_example(Type,Last)),
 9228	label_create(Clause,Type,[1-Last],Label,M).
 9229
 9230label_create(Clause,Type1,Set1,Type2,Set2,Label,M):-
 9231        split_clause(Clause,Head,Body),
 9232	nlits((Head,Body),Length),
 9233        assertz(M:'$aleph_search'(pclause,pclause(Head,Body))),
 9234	setting(depth,Depth,M),
 9235	setting(prooftime,Time,M),
 9236	setting(proof_strategy,Proof,M),
 9237        prove(Depth/Time/Proof,Type1,(Head:-Body),Set1,Cover1,_,M),
 9238        prove(Depth/Time/Proof,Type2,(Head:-Body),Set2,Cover2,_,M),
 9239	retractall(M:'$aleph_search'(pclause,_)),
 9240        assemble_label(Cover1,Cover2,Length,Label), !.
 9241
 9242label_create(Clause,Type,Set,Label,M):-
 9243        split_clause(Clause,Head,Body),
 9244        assertz(M:'$aleph_search'(pclause,pclause(Head,Body))),
 9245	setting(depth,Depth,M),
 9246	setting(prooftime,Time,M),
 9247	setting(proof_strategy,Proof,M),
 9248        prove(Depth/Time/Proof,Type,(Head:-Body,M),Set,Cover,_,M),
 9249	retractall(M:'$aleph_search'(pclause,_)),
 9250	(Type = pos -> 
 9251        	assemble_label(Cover,unknown,unknown,Label);
 9252        	assemble_label(unknown,Cover,unknown,Label)).
 9253
 9254label_pcover(Label,P):-
 9255	extract_cover(pos,Label,P).
 9256label_ncover(Label,N):-
 9257	extract_cover(neg,Label,N).
 9258
 9259label_union([],Label,Label):- !.
 9260label_union(Label,[],Label):- !.
 9261label_union(Label1,Label2,Label):-
 9262        extract_cover(pos,Label1,Pos1),
 9263        extract_cover(pos,Label2,Pos2),
 9264        extract_cover(neg,Label1,Neg1),
 9265        extract_cover(neg,Label2,Neg2),
 9266        extract_length(Label1,L1),
 9267        extract_length(Label2,L2),
 9268        update_list(Pos2,Pos1,Pos),
 9269        update_list(Neg2,Neg1,Neg),
 9270        Length is L1 + L2,
 9271        list_to_intervals(Pos,PCover),
 9272        list_to_intervals(Neg,NCover),
 9273        assemble_label(PCover,NCover,Length,Label).
 9274
 9275label_print_examples(Type,Label,M):-
 9276        extract_cover(Type,Label,C),
 9277	examples(Type,C,M).
 9278
 9279label_print_eval([],_M):- !.
 9280label_print_eval(Label,M):-
 9281	Eval = coverage,
 9282	evalfn(Eval,Label,Val,M),
 9283	print_eval(Eval,Val).
 9284
 9285print_eval(Evalfn,Val):-
 9286	evalfn_name(Evalfn,Name),
 9287	p1_message(Name), p_message(Val).
 9288
 9289
 9290eval_rule(0,Label,M):-
 9291	M:'$aleph_global'(hypothesis,hypothesis(_,Clause,_,_)), !,
 9292	label_create(Clause,Label,M),
 9293	p_message('Rule 0'),
 9294	pp_dclause(Clause,M),
 9295	extract_count(pos,Label,PC),
 9296	extract_count(neg,Label,NC),
 9297	extract_length(Label,L),
 9298	label_print_eval([PC,NC,L],M),
 9299	nl.
 9300eval_rule(ClauseNum,Label,M):-
 9301	integer(ClauseNum),
 9302	ClauseNum > 0,
 9303	M:'$aleph_global'(theory,theory(ClauseNum,_,Clause,_,_)),
 9304	!,
 9305	label_create(Clause,Label,M),
 9306	extract_count(pos,Label,PC),
 9307	extract_count(neg,Label,NC),
 9308	concat(['Rule ',ClauseNum],RuleTag),
 9309	(setting(evalfn,posonly,M) ->
 9310		concat(['Pos cover = ',PC,' Rand cover = ',NC],CoverTag);
 9311		concat(['Pos cover = ',PC,' Neg cover = ',NC],CoverTag)),
 9312	p1_message(RuleTag), p_message(CoverTag),
 9313	pp_dclause(Clause,M),
 9314	setting(verbosity,V,M),
 9315	(V >= 2 ->
 9316		p_message('positive examples covered'),
 9317		label_print_examples(pos,Label,M),
 9318		p_message('negative examples covered'),
 9319		label_print_examples(neg,Label,M);
 9320		true),
 9321	nl.
 9322eval_rule(_,_,_M).
 9323
 9324
 9325evalfn(Label,Val,M):-
 9326	(setting(evalfn,Eval,M)->true;Eval=coverage,M),
 9327	evalfn(Eval,Label,Val,M).
 9328
 9329evalfn_name(compression,'compression').
 9330evalfn_name(coverage,'pos-neg').
 9331evalfn_name(accuracy,'accuracy').
 9332evalfn_name(wracc,'novelty').
 9333evalfn_name(laplace,'laplace estimate').
 9334evalfn_name(pbayes,'pseudo-bayes estimate').
 9335evalfn_name(auto_m,'m estimate').
 9336evalfn_name(mestimate,'m estimate').
 9337evalfn_name(mse,'mse').
 9338evalfn_name(posonly,'posonly bayes estimate').
 9339evalfn_name(entropy,'entropy').
 9340evalfn_name(gini,'gini value').
 9341evalfn_name(sd,'standard deviation').
 9342evalfn_name(user,'user defined cost').
 9343
 9344evalfn(compression,[P,N,L|_],Val,_M):-
 9345	(P = -inf -> Val is -inf;
 9346        	Val is P - N - L + 1), !.
 9347evalfn(coverage,[P,N,_|_],Val,_M):-
 9348	(P = -inf -> Val is -inf;
 9349		Val is P - N), !.
 9350evalfn(laplace,[P,N|_],Val,_M):-
 9351	(P = -inf -> Val is 0.5;
 9352		Val is (P + 1) / (P + N + 2)), !.
 9353% the evaluation function below is due to Steve Moyle's implementation
 9354% of the work by Lavrac, Flach and Zupan
 9355evalfn(wracc,[P,N|_],Val,M):-
 9356	(M:'$aleph_search'(clauseprior,Total-[P1-pos,_]) ->
 9357		Val is P/Total - (P1/Total)*((P+N)/Total);
 9358		Val is -0.25), !.
 9359evalfn(entropy,[P,N|_],Val,_M):-
 9360	(P = -inf ->  Val is 1.0;
 9361		((P is 0); (N is 0) -> Val is 0.0;
 9362			Total is P + N,
 9363			P1 is P/Total,
 9364			Q1 is 1-P1,
 9365			Val is -(P1*log(P1) + Q1*log(Q1))/log(2)
 9366		)
 9367	), !.
 9368evalfn(gini,[P,N|_],Val,_M):-
 9369	(P = -inf -> Val is 1.0;
 9370		Total is P + N,
 9371		P1 is P/Total,
 9372		Val is 2*P1*(1-P1)), !.
 9373evalfn(accuracy,[P,N|_],Val,_M):-
 9374	((P = -inf; P+N =:= 0) -> Val is 0.5;
 9375		Val is P / (P + N)), !.
 9376% the evaluation functions below are due to James Cussens
 9377evalfn(pbayes,[P,N|_],Val,M):-
 9378        (P = -inf -> Val is 0.5;
 9379                Acc is P/(P+N),
 9380                setting(prior,PriorD,M),
 9381		normalise_distribution(PriorD,NPriorD),
 9382		aleph_member1(Prior-pos,NPriorD),
 9383                (0 is Prior-Acc ->
 9384                    Val=Prior;
 9385                K is (Acc*(1 - Acc)) / ((Prior-Acc)^2 ),
 9386                Val is (P + K*Prior) / (P + N + K))), !.
 9387evalfn(posonly,[P,0,L|_],Val,M):-
 9388        M:'$aleph_global'(size,size(rand,RSize)),
 9389        Val is log(P) + log(RSize+2.0) - (L+1)/P, !.
 9390evalfn(auto_m,[P,N|_],Val,M):-
 9391        (P = -inf -> Val is 0.5;
 9392                Cover is P + N,
 9393                setting(prior,PriorD,M),
 9394		normalise_distribution(PriorD,NPriorD),
 9395		aleph_member1(Prior-pos,NPriorD),
 9396                K is sqrt(Cover),
 9397                Val is (P + K*Prior) / (Cover+K)), !.
 9398evalfn(mestimate,[P,N|_],Val,M):-
 9399        (P = -inf -> Val is 0.5;
 9400                Cover is P + N,
 9401                setting(prior,PriorD,M),
 9402		normalise_distribution(PriorD,NPriorD),
 9403		aleph_member1(Prior-pos,NPriorD),
 9404                (setting(m,MM,M) -> K = MM; K is sqrt(Cover)),
 9405                Val is (P + K*Prior) / (Cover+K)), !.
 9406evalfn(_,_,X,_M):- X is -inf.
 9407
 9408
 9409assemble_label(P,N,L,[P,N,L]).
 9410
 9411extract_cover(pos,[P,_,_],P1):-
 9412        intervals_to_list(P,P1), !.
 9413extract_cover(neg,[_,N,_],N1):-
 9414        intervals_to_list(N,N1),!.
 9415extract_cover(_,[]).
 9416
 9417extract_count(pos,[P,_,_],P1):-
 9418	interval_count(P,P1), !.
 9419extract_count(neg,[_,N,_],N1):-
 9420	interval_count(N,N1), !.
 9421extract_count(neg,_,0).
 9422
 9423
 9424extract_pos([P|_],P).
 9425extract_neg([_,N|_],N).
 9426extract_length([_,_,L|_],L).
 9427
 9428get_start_label(_,[0,0,0,F],M):-
 9429	(setting(interactive,true,M); setting(search,ic,M)), !,
 9430	F is -inf.
 9431get_start_label(user,[1,0,2,F],_M):- !, F is -inf.
 9432get_start_label(entropy,[1,0,2,-0.5],_M):- !.
 9433get_start_label(gini,[1,0,2,-0.5],_M):- !.
 9434get_start_label(wracc,[1,0,2,-0.25],_M):- !.
 9435get_start_label(Evalfn,[1,0,2,Val],M):-
 9436	evalfn(Evalfn,[1,0,2],Val,M).
 9437
 9438
 9439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 9440% I / O   S T U F F
 9441
 9442% read_all(+Prefix)
 9443%	read background and examples
 9444read_all(M:Prefix):-
 9445	initialize(M),
 9446	read_all(Prefix,Prefix,Prefix,M).
 9447
 9448% read_all/2 and read_all/3 largely
 9449% provided by Stasinos Konstantopoulos and Mark Reid
 9450read_all(BPrefix,EPrefix):-
 9451	read_all(BPrefix,EPrefix,EPrefix).
 9452
 9453read_all(Back,Pos,Neg,M):-
 9454	clean_up(M),
 9455	reset(M),
 9456	read_background(Back,M),
 9457	read_examples(Pos,Neg,M), 	
 9458	record_targetpred(M), 	
 9459	check_recursive_calls(M),
 9460	check_prune_defs(M),
 9461	check_user_search(M),
 9462	check_posonly(M),
 9463	check_auto_refine(M),
 9464	check_abducibles(M).
 9465
 9466read_background(Back,M):-
 9467	construct_name(background,Back,File,M),
 9468	consult(M:File),
 9469	broadcast(background(loaded)).
 9470
 9471read_examples(Pos,Neg,M):-
 9472	(setting(train_pos,PosF,M) ->
 9473		set(use_file_extensions,false,M),
 9474		read_examples_files(pos,PosF,_,M),
 9475		noset(use_file_extensions,M);
 9476		read_examples_files(pos,Pos,PosF,M),
 9477		set(train_pos,PosF,M)
 9478	),
 9479	(setting(train_neg,NegF,M) ->
 9480		set(use_file_extensions,false,M),
 9481		read_examples_files(neg,NegF,_,M),
 9482		noset(use_file_extensions,M);
 9483		read_examples_files(neg,Neg,NegF,M),
 9484		set(train_neg,NegF,M)
 9485	),
 9486	M:'$aleph_global'(size,size(pos,P)),
 9487	M:'$aleph_global'(size,size(neg,N)),
 9488	set_lazy_recalls(M),
 9489	(setting(prior,_,M) -> true;
 9490		normalise_distribution([P-pos,N-neg],Prior),
 9491		set(prior,Prior,M)
 9492	),
 9493	reset_counts(M),
 9494	asserta(M:'$aleph_global'(last_clause,last_clause(0))),
 9495	broadcast(examples(loaded)).
 9496
 9497aleph_read_pos_examples(Type,M) :-
 9498	broadcast(background(loaded)),
 9499	clean_up_examples(Type,M),
 9500	asserta(M:'$aleph_global'(size,size(Type,0))),
 9501	M:'$aleph_global'(size,size(Type,N)),
 9502	(N > 0 -> Ex = [1-N]; Ex = []),
 9503	asserta(M:'$aleph_global'(atoms,atoms(Type,Ex))),
 9504	asserta(M:'$aleph_global'(atoms_left,atoms_left(Type,Ex))),
 9505	asserta(M:'$aleph_global'(last_example,last_example(Type,N))).
 9506aleph_read_neg_examples(Type,M) :-
 9507	clean_up_examples(Type,M),
 9508	asserta(M:'$aleph_global'(size,size(Type,0))),
 9509	/*
 9510	record_example(nocheck,neg,eastbound(west1),_),
 9511	record_example(nocheck,neg,eastbound(west2),_),
 9512	record_example(nocheck,neg,eastbound(west3),_),
 9513	record_example(nocheck,neg,eastbound(west4),_),
 9514	record_example(nocheck,neg,eastbound(west5),N1),
 9515	*/
 9516	%my_record_examples(Type),
 9517	%findall(C,M:inc(C),L),
 9518	M:'$aleph_global'(size,size(Type,N)),
 9519	(N > 0 -> Ex = [1-N]; Ex = []),
 9520	asserta(M:'$aleph_global'(atoms,atoms(Type,Ex))),
 9521	asserta(M:'$aleph_global'(atoms_left,atoms_left(Type,Ex))),
 9522	asserta(M:'$aleph_global'(last_example,last_example(Type,N))).
 9523read_examples_files(Type,Name,F,M):-
 9524	clean_up_examples(Type,M),
 9525	asserta(M:'$aleph_global'(size,size(Type,0))),
 9526	(Name = [_|_] ->
 9527		read_examples_from_files(Name,Type,F,M);
 9528		read_examples_from_file(Type,Name,F,M)),
 9529	M:'$aleph_global'(size,size(Type,N)),
 9530	(N > 0 -> Ex = [1-N]; Ex = []),
 9531	asserta(M:'$aleph_global'(atoms,atoms(Type,Ex))),
 9532	asserta(M:'$aleph_global'(atoms_left,atoms_left(Type,Ex))),
 9533	asserta(M:'$aleph_global'(last_example,last_example(Type,N))).
 9534
 9535read_examples_from_files([],_,[],_M).
 9536read_examples_from_files([Name|Files],Type,[FileName|FileNames],M):-
 9537	read_examples_from_file(Type,Name,FileName,M),
 9538	read_examples_from_files(Files,Type,FileNames,M).
 9539
 9540read_examples_from_file(Type,Name,File,M):-
 9541	construct_name(Type,Name,File,M),
 9542	(aleph_open(File,read,Stream) ->
 9543		concat(['consulting ',Type, ' examples'],Mess),
 9544		p1_message(Mess), p_message(File);
 9545		p1_message('cannot open'), p_message(File),
 9546		fail),
 9547	repeat,
 9548	read(Stream,Example),
 9549	(Example=end_of_file-> close(Stream);
 9550		record_example(nocheck,Type,Example,_,M),
 9551		fail),
 9552	!.
 9553read_examples_from_file(_,_,'?',_M).
 9554
 9555construct_name(_,Name,Name,M):-
 9556	setting(use_file_extensions,false,M), !.
 9557construct_name(Type,Prefix,Name,_M):-
 9558	name(Prefix,PString),
 9559	file_extension(Type,SString),
 9560	aleph_append(SString,PString,FString),
 9561	name(Name,FString).
 9562
 9563file_extension(pos,Suffix):- name('.f',Suffix).
 9564file_extension(neg,Suffix):- name('.n',Suffix).
 9565file_extension(background,Suffix):- name('.b',Suffix).
 9566
 9567
 9568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 9569% M I S C.   D E F I N I T I O N S
 9570
 9571execute(C):-
 9572	system(C), !.
 9573execute(_).
 9574
 9575% store critical values of current search state
 9576store(searchstate,M):-
 9577	!,
 9578	retractall(M:'$aleph_global'(save,save(searchstate,_))),
 9579	(M:'$aleph_global'(atoms_left,atoms_left(pos,PosLeft)) ->
 9580		asserta(M:'$aleph_global'(save,
 9581				save(searchstate,atoms_left(pos,PosLeft))));
 9582		true),
 9583	(M:'$aleph_global'(atoms_left,atoms_left(neg,NegLeft)) ->
 9584		asserta(M:'$aleph_global'(save,
 9585				save(searchstate,atoms_left(neg,NegLeft))));
 9586		true),
 9587	(M:'$aleph_global'(size,size(pos,PSize)) ->
 9588		asserta(M:'$aleph_global'(save,
 9589				save(searchstate,size(pos,PSize))));
 9590		true),
 9591	(M:'$aleph_global'(size,size(neg,NSize)) ->
 9592		asserta(M:'$aleph_global'(save,
 9593				save(searchstate,size(neg,NSize))));
 9594		true),
 9595	(M:'$aleph_global'(noise,set(noise,Noise)) ->
 9596		asserta(M:'$aleph_global'(save,
 9597				save(searchstate,set(noise,Noise))));
 9598		true),
 9599	(M:'$aleph_global'(minacc,set(minacc,MinAcc)) ->
 9600		asserta(M:'$aleph_global'(save,
 9601				save(searchstate,set(minacc,MinAcc))));
 9602		true).
 9603
 9604% store current bottom clause
 9605store(bottom,M):-
 9606	!,
 9607	(M:'$aleph_global'(store_bottom,set(store_bottom,true)) ->
 9608		store_bottom;
 9609		true).
 9610
 9611store(Parameter,M):-
 9612	(M:'$aleph_global'(Parameter,set(Parameter,Value)) -> true; Value = unknown),
 9613	retractall(M:'$aleph_global'(save,save(Parameter,_))),
 9614	asserta(M:'$aleph_global'(save,save(Parameter,Value))).
 9615
 9616% store values of a list of parameters
 9617store_values([],_M).
 9618store_values([Parameter|T],M):-
 9619	store(Parameter,M),
 9620	store_values(T,M).
 9621
 9622% store all relevant info related to current bottom
 9623%	details are stored in 5 idbs:
 9624%	1. bottom: points to 2 other idbs sat_X_n and lits_X_N
 9625%	2. sat_X_N: where X is the type of the current example and N the number 
 9626%		this contains misc stuff recorded by sat/2 for use by reduce/1
 9627%	3. lits_X_N: contains the lits in bottom
 9628%	4. ovars_X_N: contains output vars of lits in bottom
 9629%	5. ivars_X_N: contains input vars of lits in bottom
 9630store_bottom(M):-
 9631	bottom_key(Num,Type,Key,true,M),
 9632	asserta(M:'$aleph_sat'(stored,stored(Num,Type,Key))),
 9633	'$aleph_sat'(lastterm,LastTerm),
 9634	asserta(M:'$aleph_sat'(lasterm,Key,LastTerm)),
 9635	'$aleph_sat'(lastvar,LastVar),
 9636	asserta(M:'$aleph_sat'(lastvar,Key,LastVar)),
 9637	'$aleph_sat'(botsize,BotSize),
 9638	asserta(M:'$aleph_sat'(botsize,Key,BotSize)),
 9639	'$aleph_sat'(lastlit,LastLit),
 9640	asserta(M:'$aleph_sat'(lastlit,Key,LastLit)),
 9641	'$aleph_sat'(hovars,HOVars),
 9642	asserta(M:'$aleph_sat'(hovars,Key,HOVars)),
 9643	'$aleph_sat'(hivars,HIVars),
 9644	asserta(M:'$aleph_sat'(hivars,Key,HIVars)),
 9645	'$aleph_sat'(eq,Eq),
 9646	asserta(M:'$aleph_sat'(eq,Key,Eq)),
 9647	'$aleph_sat_ivars'(Lit,IVars),
 9648	asserta(M:'$aleph_sat_ivars'(Lit,Key,IVars)),
 9649	'$aleph_sat_ovars'(Lit,OVars),
 9650	asserta(M:'$aleph_sat_ovars'(Lit,Key,OVars)),
 9651	'$aleph_sat_litinfo'(Lit,Depth,Atom,I,O,D),
 9652	asserta(M:'$aleph_sat_litinfo'(Lit,Key,Depth,Atom,I,O,D)),
 9653	fail.
 9654store_bottom(_M).
 9655	
 9656
 9657reinstate(searchstate,M):-
 9658	!,
 9659	retractall(M:'$aleph_global'(atoms_left,atoms_left(_,_))),
 9660	retractall(M:'$aleph_global'(size,size(_,_))),
 9661	(M:'$aleph_global'(save,save(searchstate,atoms_left(pos,PosLeft))) ->
 9662		asserta(M:'$aleph_global'(atoms_left,atoms_left(pos,PosLeft)));
 9663		true),
 9664	(M:'$aleph_global'(save,save(searchstate,atoms_left(neg,NegLeft))) ->
 9665		asserta(M:'$aleph_global'(atoms_left,atoms_left(neg,NegLeft)));
 9666		true),
 9667	(M:'$aleph_global'(save,save(searchstate,size(pos,PSize))) ->
 9668		asserta(M:'$aleph_global'(size,size(pos,PSize)));
 9669		true),
 9670	(M:'$aleph_global'(save,save(searchstate,size(neg,NSize))) ->
 9671		asserta(M:'$aleph_global'(size,size(neg,NSize)));
 9672		true),
 9673	(M:'$aleph_global'(save,save(searchstate,set(noise,Noise))) ->
 9674		set(noise,Noise,M);
 9675		true),
 9676	(M:'$aleph_global'(save,save(searchstate,set(minacc,MinAcc))) ->
 9677		set(minacc,MinAcc,M);
 9678		true),
 9679	retractall(M:'$aleph_global'(save,save(searchstate,_))).
 9680reinstate(Parameter,M):-
 9681	retract(M:'$aleph_global'(save,save(Parameter,Value))), !,
 9682	(Value = unknown -> noset(Parameter,M); set(Parameter,Value,M)).
 9683reinstate(_,_M).
 9684
 9685% reinstate list of values of parameters
 9686reinstate_values([],_M).
 9687reinstate_values([Parameter|T],M):-
 9688	reinstate(Parameter,M),
 9689	reinstate_values(T,M).
 9690
 9691% reinstate all saved values
 9692reinstate_values(M):-
 9693	reinstate_file_streams(M),
 9694	M:'$aleph_global'(save,save(_,_)), 
 9695	repeat,
 9696	retract(M:'$aleph_global'(save,save(Parameter,Value))), 
 9697	(Value = unknown -> noset(Parameter,M) ; set(Parameter,Value,M)),
 9698	\+(M:'$aleph_global'(save,save(_,_))),
 9699	!.
 9700reinstate_values(_M).
 9701
 9702reinstate_file_streams(M):-
 9703	setting(recordfile,File,M),
 9704	set(recordfile,File,M),
 9705	fail.
 9706reinstate_file_streams(M):-
 9707	setting(goodfile,File,M),
 9708	set(goodfile,File,M),
 9709	fail.
 9710reinstate_file_streams(_M).
 9711
 9712
 9713% bottom_key(?N,?T,-Key,-Flag)
 9714%	returns key that indexes bottom clause info for example N of type T
 9715%	Flag is one of "true" or "false" depending on whether bottom
 9716%	requires storing
 9717bottom_key(N,T,Key,Flag,M):-
 9718	((var(N),var(T)) ->
 9719		M:'$aleph_sat'(example,example(N,T));
 9720		true),
 9721	(setting(store_bottom,true,M) ->
 9722		(M:'$aleph_sat'(stored,stored(N,T,Key)) ->
 9723			Flag = false;
 9724			concat([T,'_',N],Key),
 9725			Flag = true
 9726		);
 9727		Key = false,
 9728		Flag = false).
 aleph_set(:Parameter:atomic, +Value:term) is det
Sets the value of a parameter. /
 9735aleph_set(M:Variable,Value):-
 9736  set(Variable,Value,M).
 9737
 9738
 9739set(Variable,Value,M):-
 9740	check_setting(Variable,Value),
 9741	(Value = inf -> V is inf;
 9742		(Value = +inf -> V is inf;
 9743			(Value = -inf -> V is -inf; V = Value)
 9744		)
 9745	),
 9746	retractall(M:'$aleph_global'(Variable,set(Variable,_))),
 9747	assertz(M:'$aleph_global'(Variable,set(Variable,V))),
 9748	broadcast(set(Variable,V)),
 9749	special_consideration(Variable,Value,M).
 aleph_setting(:Parameter:atomic, +Value:term) is det
Reads the value of a parameter. /
 9755aleph_setting(M:Variable,Value):-
 9756	setting(Variable,Value,M).
 9757
 9758setting(Variable,Value,M):-
 9759	nonvar(Variable), 
 9760	M:'$aleph_global'(Variable,set(Variable,Value1)), !,
 9761	Value = Value1.
 9762setting(Variable,Value,_M):-
 9763	default_setting(Variable,Value).
 9764
 9765noset(M:Variable):-
 9766	noset(Variable,M).
 9767
 9768noset(Variable,M):-
 9769	nonvar(Variable),
 9770        retract(M:'$aleph_global'(Variable,set(Variable,Value))), !,
 9771	rm_special_consideration(Variable,Value,M),
 9772	set_default(Variable,M).
 9773noset(_,_M).
 man(-Manual:URL) is det
returns manual URL

/

 9781man(M):-
 9782	aleph_manual(M).
 9783
 9784determinations(Pred1,Pred2,M):-
 9785        M:'$aleph_global'(determination,determination(Pred1,Pred2)).
 9786
 9787determination(Pred1,Pred2,M):-
 9788	nonvar(Pred1),
 9789	M:'$aleph_global'(determination,determination(Pred1,Pred2)), !.
 9790determination(Pred1,Pred2,M):-
 9791	noset(autorefine,M),
 9792	assertz(M:'$aleph_global'(determination,determination(Pred1,Pred2))),
 9793	(nonvar(Pred1) ->
 9794		update_backpreds(Pred1,M);
 9795		true).
 abducible(:Pred:term) is det
Pred is of the form N/A, where the atom N is the name of the predicate, and A its arity. Specifies that ground atoms with symbol N/A can be abduced if required. /
 9803abducible(M:Name/Arity):-
 9804	abducible(Name/Arity,M).
 9805
 9806abducible(Name/Arity,M):-
 9807	assertz(M:'$aleph_global'(abducible,abducible(Name/Arity))).
 commutative(:Pred:term) is det
Pred is of the form N/A, where the atom N is the name of the predicate, and A its arity. Specifies that literals with symbol N/A are commutative. /
 9815commutative(M:Name/Arity):-
 9816	commutative(Name/Arity,M).
 9817
 9818commutative(Name/Arity,M):-
 9819	assertz(M:'$aleph_global'(commutative,commutative(Name/Arity))).
 symmetric(:Pred:term) is det
Pred is of the form N/A, where the atom N is the name of the predicate, and A its arity. Specifies that literals with symbol N/A are symmetric. /
 9826symmetric(M:Name/Arity):-
 9827	symmetric(Name/Arity,M).
 9828
 9829symmetric(Name/Arity,M):-
 9830	assertz(M:'$aleph_global'(symmetric,symmetric(Name/Arity))).
 lazy_evaluate(:Pred:term) is det
Pred V is of the form N/A, where the atom N is the name of the predicate, and A its arity. Specifies that outputs and constants for literals with symbol N/A are to be evaluated lazily during the search. This is particularly useful if the constants required cannot be obtained from the bottom clause constructed by using a single example. During the search, the literal is called with a list containing a pair of lists for each input argument representing `positive' and `negative' substitutions obtained for the input arguments of the literal. These substitutions are obtained by executing the partial clause without this literal on the positive and negative examples. The user needs to provide a definition capable of processing a call with a list of list-pairs in each argument, and how the outputs are to be computed from such information. For further details see A. Srinivasan and R. Camacho, Experiments in numerical reasoning with ILP, Jnl. Logic Programming. /
 9848lazy_evaluate(M:Name/Arity):-
 9849	lazy_evaluate(Name/Arity,M).
 9850
 9851lazy_evaluate(Name/Arity,M):-
 9852        assertz(M:'$aleph_global'(lazy_evaluate,lazy_evaluate(Name/Arity))).
 model(:Pred:term) is det
Pred is of the form N/A, where the atom N is the name of the predicate, and A its arity. Specifies that predicate N/A will be used to construct and execute models in the leaves of model trees. This automatically results in predicate N/A being lazily evaluated (see lazy_evaluate/1). /
 9862model(M:Name/Arity):-
 9863	model(Name/Arity,M).
 9864
 9865model(Name/Arity,M):-
 9866        assertz(M:'$aleph_global'(model,model(Name/Arity))).
 positive_only(:Pred:term) is det
Pred is of the form N/A, where the atom N is the name of the predicate, and A its arity. States that only positive substitutions are required during lazy evaluation of literals with symbol N/A. This saves some theorem-proving effort. /
 9876positive_only(M:Name/Arity):-
 9877	positive_only(Name/Arity,M).
 9878
 9879positive_only(Name/Arity,M):-
 9880	assertz(M:'$aleph_global'(positive_only,positive_only(Name/Arity))).
 mode(:Recall:int, +PredicateMode:term) is det
Declare the mode of call for predicates that can appear in any clause hypothesised by Aleph /
 9886mode(M:Recall,Pred):-
 9887	mode(Recall,Pred,M).
 9888
 9889mode(Recall,Pred,M):-
 9890	modeh(Recall,Pred,M),
 9891	modeb(Recall,Pred,M).
 9892
 9893modes(N/A,Mode,M):-
 9894        Mode = modeh(_,Pred),
 9895        M:'$aleph_global'(modeh,Mode),
 9896        functor(Pred,N,A).
 9897modes(N/A,Mode,M):-
 9898        Mode = modeb(_,Pred),
 9899        M:'$aleph_global'(modeb,Mode),
 9900        functor(Pred,N,A).
 modeh(:Recall:int, +PredicateMode:term) is det
Recall is one of: a positive integer or *. Mode is a mode template as in a mode/2 declaration. Declares a mode for the head of a hypothesised clause. Required when evalfn is posonly. /
 9907modeh(M:Recall,Pred):-
 9908	modeh(Recall,Pred,M).
 9909
 9910modeh(Recall,Pred,M):-
 9911	(M:'$aleph_global'(mode,mode(Recall,Pred)) -> true;
 9912		noset(autorefine,M),
 9913		assertz(M:'$aleph_global'(modeh,modeh(Recall,Pred))),
 9914		assertz(M:'$aleph_global'(mode,mode(Recall,Pred))),
 9915        	functor(Pred,Name,Arity),
 9916        	update_backpreds(Name/Arity,M)).
 modeb(:Recall:int, +PredicateMode:term) is det
Recall is one of: a positive integer or *. Mode is a mode template as in a mode/2 declaration. Declares a mode for a literal in the body of a hypothesised clause. /
 9923modeb(M:Recall,Pred):-
 9924	modeb(Recall,Pred,M).
 9925
 9926modeb(Recall,Pred,M):-
 9927	(M:'$aleph_global'(modeb,modeb(Recall,Pred)) -> true;
 9928		noset(autorefine,M),
 9929		assertz(M:'$aleph_global'(modeb,modeb(Recall,Pred))),
 9930		(M:'$aleph_global'(mode,mode(Recall,Pred)) -> true;
 9931			assertz(M:'$aleph_global'(mode,mode(Recall,Pred))))).
 9932
 9933% add_determinations(+PSym,Stratified)
 9934% add determination declarations for a background predicate
 9935% these are obtained from the determinations of the target predicate
 9936% If Stratified is true then only stratified definitions are allowed
 9937add_determinations(PSym,Stratified,M):-
 9938	M:'$aleph_global'(targetpred,targetpred(Target)),
 9939	determinations(Target,OtherPred,M),
 9940	(Stratified = true -> OtherPred \= Target; true),
 9941	determination(PSym,OtherPred,M),
 9942	fail.
 9943add_determinations(_,_,_M).
 9944
 9945% add_modes(+PSym)
 9946% add modes declarations for a (new) predicate
 9947% these are obtained from the modes of the target predicate
 9948add_modes(Name/_,M):-
 9949	M:'$aleph_global'(targetpred,targetpred(Target)),
 9950	modes(Target,Mode,M),
 9951	Mode =.. [ModeType,Recall,TargetMode],
 9952	TargetMode =.. [_|Args],
 9953	PredMode =.. [Name|Args],
 9954	NewMode =.. [ModeType,Recall,PredMode,M],
 9955	call(NewMode),
 9956	fail.
 9957add_modes(_,_M).
 9958
 9959feature(Id,Feature,M):-
 9960	M:'$aleph_feature'(feature,feature(Id,_,_,Template,Body)), 
 9961	Feature = (Template:-Body).
 9962
 9963gen_feature(Feature,Label,Class,M):-
 9964	nonvar(Feature), !,
 9965	gen_featurenum(Id,M),
 9966	split_clause(Feature,Template,Body),
 9967	assertz(M:'$aleph_feature'(feature,feature(Id,Label,Class,Template,Body))).
 show(+V:atomic) is det
Different values of V result in showing the following.

/

 9997show(M:S):-
 9998	show(S,M).
 9999
10000show(settings,M):-
10001	nl,
10002	p_message('settings'),
10003	findall(P-V,M:'$aleph_global'(P,set(P,V)),L),
10004	sort(L,L1),
10005	aleph_member(Parameter-Value,L1),
10006        tab(8), write(Parameter=Value), nl,
10007        fail.
10008show(determinations,M):-
10009	nl,
10010	p_message('determinations'),
10011	show_global(determination,determination(_,_),M).
10012show(modes,M):-
10013	nl,
10014	p_message('modes'),
10015	show_global(mode,mode(_,_),M).
10016show(modehs,M):-
10017	nl,
10018	p_message('modehs'),
10019	show_global(modeh,modeh(_,_),M).
10020show(modebs,M):-
10021	nl,
10022	p_message('modebs'),
10023	show_global(modeb,modeb(_,_),M).
10024show(sizes,M):-
10025	nl,
10026	p_message('sizes'),
10027	show_global(size,size(_,_),M).
10028show(bottom,M):-
10029	nl,
10030	p_message('bottom clause'),
10031	setting(verbosity,V,M),
10032	V > 0,
10033	M:'$aleph_sat'(lastlit,Last),
10034	get_clause(1,Last,[],FlatClause,M),
10035	pp_dlist(FlatClause,M).
10036show(theory,M):-
10037        nl,
10038        p_message('theory'),
10039        nl,
10040        M:'$aleph_global'(rules,rules(L)),
10041        aleph_reverse(L,L1),
10042        aleph_member(ClauseNum,L1),
10043	M:'$aleph_global'(theory,theory(ClauseNum,_,_,_,_)),
10044	eval_rule(ClauseNum,_,M),
10045	% pp_dclause(Clause),
10046        fail.
10047show(theory,M):-
10048	get_performance(M).
10049show(pos,M):-
10050	nl,
10051	p_message('positives'),
10052	store(greedy,M),
10053	examples(pos,_,M),
10054	reinstate(greedy,M),
10055	fail.
10056show(posleft,M):-
10057	nl,
10058	p_message('positives left'),
10059        M:example(_,pos,Atom),
10060	\+(Atom),
10061        write(Atom), write('.'), nl,
10062	fail.
10063show(neg,M):-
10064	nl,
10065	p_message('negatives'),
10066	store(greedy,M),
10067	examples(neg,_,M),
10068	reinstate(greedy,M),
10069	fail.
10070show(rand,M):-
10071	nl,
10072	p_message('random'),
10073	examples(rand,_,M),
10074	fail.
10075show(uspec,M):-
10076	nl,
10077	p_message('uspec'),
10078	examples(uspec,_,M),
10079	fail.
10080show(gcws,M):-
10081	nl,
10082	p_message('gcws hypothesis'),
10083	M:'$aleph_search'(gcwshyp,hypothesis(_,C,_,_)),
10084	pp_dclause(C,M),
10085	fail.
10086show(abgen,M):-
10087	nl,
10088	p_message('abduced hypothesis'),
10089	M:'$aleph_search'(abgenhyp,hypothesis(_,AbGen,_,_)),
10090	aleph_member(C,AbGen),
10091	pp_dclause(C,M),
10092	fail.
10093show(hypothesis,M):-
10094	setting(portray_hypothesis,Pretty,M),
10095	aleph_portray(hypothesis,Pretty,M),
10096	fail.
10097show(search,M):-
10098	setting(portray_search,Pretty,M),
10099	aleph_portray(search,Pretty,M).
10100show(good,M):-
10101	setting(good,true,M),
10102	nl,
10103        p_message('good clauses'),
10104        (setting(minscore,FMin,M) -> true; FMin is -inf),
10105        setting(evalfn,Evalfn,M),
10106	M:'$aleph_good'(_,Label,Clause),
10107	Label = [_,_,_,F|_],
10108	F >= FMin,
10109	pp_dclause(Clause,M),
10110	show_stats(Evalfn,Label),
10111	fail.
10112show(good,M):-
10113	setting(good,true,M),
10114	setting(goodfile,File,M),
10115	aleph_open(File,read,Stream),
10116        (setting(minscore,FMin,M) -> true; FMin is -inf),
10117        setting(evalfn,Evalfn,M),
10118	repeat,
10119	read(Stream,Fact),
10120	(Fact = M:'$aleph_good'(_,Label,Clause) ->
10121		Label = [_,_,_,F|_],
10122		F >= FMin,
10123        	show_stats(Evalfn,Label),
10124        	pp_dclause(Clause,M),
10125		fail;
10126		close(Stream), !
10127	).
10128show(features,M):-
10129        setting(evalfn,Evalfn,M),
10130	(M:'$aleph_feature'(feature,_) -> true;
10131		gen_features(M)),
10132        p_message('features from good clauses'),
10133	M:'$aleph_feature'(feature,feature(Id,Label,_,Head,Body)),
10134	show_stats(Evalfn,Label),
10135        pp_dclause(feature(Id,(Head:-Body)),M),
10136	fail.
10137show(constraints,M):-
10138	setting(good,true,M),
10139	nl,
10140	p_message('constraints'),
10141	setting(noise,N,M),
10142	FMin is -N,
10143	M:'$aleph_good'(_,Label,Clause),
10144	split_clause(Clause,false,_),
10145	Label = [_,_,_,F],
10146	F >= FMin,
10147        pp_dclause(Clause,M),
10148        show_stats(coverage,Label),
10149	fail.
10150show(constraints,M):-
10151	show(aleph_false/0,M).
10152show(Name/Arity,M):-
10153	functor(Pred,Name,Arity),
10154	%current_predicate(M:Name,Pred),
10155        nl,
10156        p1_message('definition'), p_message(Name/Arity),
10157	clause(M:Pred,Body),
10158	\+(in(Body,'$aleph_search'(pclause,pclause(_,_)),M)),
10159	pp_dclause((Pred:-Body),M),
10160	fail.
10161show(train_pos,M):-
10162	setting(portray_examples,Pretty,M),
10163	aleph_portray(train_pos,Pretty,M).
10164show(train_neg,M):-
10165	setting(portray_examples,Pretty,M),
10166	aleph_portray(train_neg,Pretty,M).
10167show(test_pos,M):-
10168	setting(portray_examples,Pretty,M),
10169	aleph_portray(test_pos,Pretty,M).
10170show(test_neg,M):-
10171	setting(portray_examples,Pretty,M),
10172	aleph_portray(test_neg,Pretty,M).
10173show(_,_M).
10174
10175settings(M):-
10176	show(settings,M).
 good_clauses(:GoodClauses:list) is det
Good clauses found in searches conducted so far (good clauses all have a utility above that specified by minscore). /
10184good_clauses(M:GC):-
10185	good_clauses(GC,M).
10186
10187good_clauses(GC,M):-
10188        (setting(minscore,FMin,M) -> true; FMin is -inf),
10189	findall(Clause,
10190		(M:'$aleph_good'(_,Label,Clause),
10191		Label = [_,_,_,F|_],
10192		F >= FMin),GC).
10193
10194% examples(?Type,?List)
10195% show all examples numbers in List of Type
10196examples(Type,List,M):-
10197	setting(portray_literals,Pretty,M),
10198        M:example(Num,Type,Atom),
10199        aleph_member1(Num,List),
10200	aleph_portray(Atom,Pretty,M), write('.'), nl,
10201        fail.
10202examples(_,_,_M).
 bottom(:BottomClause:term) is det
BottomClause is the current bottom clause. /
10209bottom(M:Clause):-
10210	bottom(Clause,M).
10211
10212bottom(Clause,M):-
10213	M:'$aleph_sat'(lastlit,Last), 
10214	get_clause(1,Last,[],ClauseList,M),
10215	list_to_clause(ClauseList,Clause).
10216
10217% posleft(-List)
10218%	returns positive examples left to be covered
10219posleft(PList,M):-
10220	M:'$aleph_global'(atoms_left,atoms_left(pos,PosLeft)),
10221	intervals_to_list(PosLeft,PList).
10222
10223% write_rules/0 due to Mark Reid
10224write_rules(M):-
10225	setting(rulefile,File,M),
10226	write_rules(File), !.
10227write_rules(_M).
10228
10229write_features(M):-
10230	setting(featurefile,File,M),
10231	write_features(File,M), !.
10232write_features(_M).
10233
10234write_rules(File,M):-
10235        aleph_open(File,write,Stream),
10236        set_output(Stream),
10237        M:'$aleph_global'(rules,rules(L)),
10238        aleph_reverse(L,L1),
10239        write_rule(L1,M),
10240        flush_output(Stream),
10241        set_output(user_output).
10242
10243write_rule(Rules,M):-
10244        aleph_member(RuleId,Rules),
10245        M:'$aleph_global'(theory,theory(RuleId,_,Rule,_,_)),
10246        pp_dclause(Rule,M),
10247        fail.
10248write_rule(_,_M).
10249
10250write_features(File,M):-
10251        aleph_open(File,write,Stream),
10252        set_output(Stream),
10253	listing(M:'$aleph_feature'/2),
10254        close(Stream),
10255        set_output(user_output).
10256write_features(_,_M).
10257
10258
10259best_hypothesis(Head1,Body1,[P,N,L],M):-
10260	M:'$aleph_search'(selected,selected([P,N,L|_],Clause,_,_)),
10261	split_clause(Clause,Head2,Body2), !,
10262	Head1 = Head2, Body1 = Body2.
 hypothesis(:Head:term, -Body:term, -Label:list) is det
Head is the head of the current hypothesised clause. Body is the body of the current hypothesised clause. Label is the list [P,N,L] where P is the positive examples covered by the hypothesised clause, N is the negative examples covered by the hypothesised clause, and L is the number of literals in the hypothesised clause.

/

10275hypothesis(M:Head1,Body1,Label):-
10276	hypothesis(Head1,Body1,Label,M).
 hypothesis(-Head:term, -Body:term, -Label:list, +Module:atomic) is det
Head is the head of the current hypothesised clause. Body is the body of the current hypothesised clause. Label is the list [P,N,L] where P is the positive examples covered by the hypothesised clause, N is the negative examples covered by the hypothesised clause, and L is the number of literals in the hypothesised clause. Module is the module of the input file. Internal predicates. /
10289hypothesis(Head1,Body1,Label,M):-
10290	M:'$aleph_search'(pclause,pclause(Head2,Body2)), !,
10291	Head1 = Head2, Body1 = Body2,
10292	get_hyp_label((Head2:-Body2),Label,M).
10293hypothesis(Head1,Body1,Label,M):-
10294        M:'$aleph_global'(hypothesis,hypothesis(_,Theory,_,_)),
10295	(Theory = [_|_] -> aleph_member(Clause,Theory);
10296		Theory = Clause),
10297	split_clause(Clause,Head2,Body2), 
10298	Head1 = Head2, Body1 = Body2,
10299	get_hyp_label((Head2:-Body2),Label,M).
 rdhyp(:V:var) is det
Read a hypothesised clause from the user. Internal predicate, to be called as rdhyp/0.

/

10308rdhyp(M:_):-
10309	retractall(M:'$aleph_search'(pclause,_)),
10310	retractall(M:'$aleph_search'(covers,_)),
10311	retractall(M:'$aleph_search'(coversn,_)),
10312        read(Clause),
10313        add_hyp(Clause,M),
10314        nl,
10315        show(hypothesis,M).
 addhyp_i(:V:var) is det
Add current hypothesised clause to theory. If a search is interrupted, then the current best hypothesis will be added to the theory. Internal predicate, to be called as addhyp/0.

/

10326addhyp_i(M:_):-
10327	addhyp(M).
10328
10329addhyp(M):-
10330	M:'$aleph_global'(hypothesis,hypothesis(Label,Theory,PCover,NCover)),
10331	Theory = [_|_], !,
10332	add_theory(Label,Theory,PCover,NCover,M).
10333addhyp(M):-
10334        M:'$aleph_global'(hypothesis,hypothesis(Label,_,PCover,_)), !,   
10335        rm_seeds(M),
10336        worse_coversets(PCover,pos,Label,Worse,M),
10337        (Worse = [] -> true;
10338        	M:'$aleph_global'(last_clause,last_clause(NewClause)),
10339                update_coversets(Worse,NewClause,pos,Label,M)), !.
10340addhyp(M):-
10341        M:'$aleph_search'(selected,selected(Label,RClause,PCover,NCover)), !,
10342        add_hyp(Label,RClause,PCover,NCover,M),
10343        rm_seeds(M),
10344        worse_coversets(PCover,pos,Label,Worse,M),
10345        (Worse = [] -> true;
10346        	M:'$aleph_global'(last_clause,last_clause(NewClause)),
10347                update_coversets(Worse,NewClause,pos,Label,M)), !.
10348
10349% add bottom clause as hypothesis
10350%	provided minacc, noise and search constraints are met
10351%	otherwise the example saturated is added as hypothesis
10352add_bottom(Bottom,M):-
10353	retractall(M:'$aleph_search'(selected,selected(_,_,_,_))),
10354	bottom(Bottom,M),
10355	add_hyp(Bottom,M),
10356        M:'$aleph_global'(hypothesis,hypothesis(Label,Clause,_,_)),
10357	(clause_ok(Clause,Label,M) -> true;
10358		M:'$aleph_sat'(example,example(Num,Type)),
10359		M:example(Num,Type,Example),
10360		retract(M:'$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
10361		setting(evalfn,Evalfn,M),
10362		complete_label(Evalfn,Example,[1,0,1],Label1),
10363		asserta(M:'$aleph_global'(hypothesis,hypothesis(Label1,(Example:-true),[Num-Num],[])))).
10364
10365	
10366% specialise a hypothesis by recursive construction of
10367% abnormality predicates
 sphyp_i(:V:var) is det
Specialise a hypothesis by recursive construction of abnormality predicates. Internal predicate, to be called as sphyp/0. /
10376sphyp_i(M:_):-
10377	sphyp(M).
10378
10379sphyp(M):-
10380	retractall(M:'$aleph_search'(sphyp,hypothesis(_,_,_,_))),
10381	retractall(M:'$aleph_search'(gcwshyp,hypothesis(_,_,_,_))),
10382        retract(M:'$aleph_global'(hypothesis,
10383				hypothesis([P,N,L|T],Clause,PCover,NCover))),
10384        asserta(M:'$aleph_search'(sphyp,hypothesis([P,N,L|T],Clause,PCover,NCover))),
10385        store(searchstate,M),
10386        gcws(M),
10387        retractall(M:'$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
10388        asserta(M:'$aleph_global'(hypothesis,
10389			hypothesis([P,N,L|T],Clause,PCover,NCover))),
10390        reinstate(searchstate,M).
 addgcws_i(:V:var) is det
Add hypothesis constructed by performing GCWS to theory. Internal predicate, to be called as addgcws/0.

/

10399addgcws_i(M:_):-
10400	addgcws(M).
10401
10402addgcws(M):-
10403        retract(M:'$aleph_search'(gcwshyp,hypothesis(Label,C,P,N))), !,   
10404	asserta(M:'$aleph_search'(gcwshyp,hypothesis(Label,C,P,N))),
10405	addhyp(M),
10406	add_gcws(M).
 rmhyp_i(:V:var) is det
Remove the current hypothesised clause from theory Internal predicate, to be called as rmhyp/0.

/

10414rmhyp_i(M:_):-
10415	rmhyp(M).
10416
10417rmhyp(M):-
10418        retract(M:'$aleph_search'(pclause,pclause(Head,Body))),
10419        asserta(M:'$aleph_local'(pclause,pclause(Head,Body))), !.
10420rmhyp(M):-
10421        retract(M:'$aleph_global'(hypothesis,hypothesis(Label,Clause1,P,N))),
10422        asserta(M:'$aleph_local'(hypothesis,hypothesis(Label,Clause1,P,N))), !.
10423rmhyp(_).
 covers(-P:int) is det
Show positive examples covered by hypothesised clause.

/

10432covers(M:PC):-
10433        get_hyp(Hypothesis,M),
10434        label_create(Hypothesis,Label,M),
10435        extract_cover(pos,Label,P),
10436        examples(pos,P,M),
10437	length(P,PC),
10438	p1_message('examples covered'),
10439	p_message(PC),
10440	retractall(M:'$aleph_search'(covers,_)),
10441	asserta(M:'$aleph_search'(covers,covers(P,PC))).
 coversn(-N:int) is det
Show negative examples covered by hypothesised clause.

/

10449coversn(M:NC):-
10450        get_hyp(Hypothesis,M),
10451        label_create(Hypothesis,Label,M),
10452        extract_cover(neg,Label,N),
10453        examples(neg,N,M),
10454	length(N,NC),
10455	p1_message('examples covered'),
10456	p_message(NC),
10457	retractall(M:'$aleph_search'(coversn,_)),
10458	asserta(M:'$aleph_search'(coversn,coversn(N,NC))).
10459
10460% covers(-Number)
10461% 	as in covers/0, but first checks if being done
10462% 	within a greedy search
10463covers(P,M):-
10464	get_hyp(Hypothesis,M),
10465	(setting(greedy,true,M) -> 
10466		M:'$aleph_global'(atoms,atoms_left(pos,Pos));
10467		M:'$aleph_global'(atoms,atoms(pos,Pos))),
10468	label_create(Hypothesis,pos,Pos,Label,M),
10469	retractall(M:'$aleph_search'(covers,_)),
10470	extract_pos(Label,PCover),
10471	interval_count(PCover,P),
10472	asserta(M:'$aleph_search'(covers,covers(PCover,P))).
10473
10474% coversn(-Number)
10475% 	as in coversn/0, but first checks if being done
10476% 	within a greedy search
10477coversn(N,M):-
10478	get_hyp(Hypothesis,M),
10479	(setting(greedy,true,M) ->
10480		M:'$aleph_global'(atoms_left,atoms_left(neg,Neg));
10481		M:'$aleph_global'(atoms_left,atoms(neg,Neg))),
10482	label_create(Hypothesis,neg,Neg,Label,M),
10483	retractall(M:'$aleph_search'(coversn,_)),
10484	extract_neg(Label,NCover),
10485	interval_count(NCover,N),
10486	asserta(M:'$aleph_search'(coversn,coverns(NCover,N))).
10487
10488% covers(-List,-Number)
10489% 	as in covers/1, but returns list of examples covered and their count
10490covers(PList,P,M):-
10491	get_hyp(Hypothesis,M),
10492	(setting(greedy,true,M) -> 
10493		M:'$aleph_global'(atoms,atoms_left(pos,Pos));
10494		M:'$aleph_global'(atoms,atoms(pos,Pos))),
10495	label_create(Hypothesis,pos,Pos,Label,M),
10496	retractall(M:'$aleph_search'(covers,_)),
10497	extract_pos(Label,PCover),
10498	intervals_to_list(PCover,PList),
10499	length(PList,P),
10500	asserta(M:'$aleph_search'(covers,covers(PCover,P))).
10501
10502% coversn(-List,-Number)
10503% 	as in coversn/1, but returns list of examples covered and their count
10504coversn(NList,N,M):-
10505	get_hyp(Hypothesis,M),
10506	(setting(greedy,true,M) ->
10507		M:'$aleph_global'(atoms_left,atoms_left(neg,Neg));
10508		M:'$aleph_global'(atoms_left,atoms(neg,Neg))),
10509	label_create(Hypothesis,neg,Neg,Label,M),
10510	retractall(M:'$aleph_search'(coversn,_)),
10511	extract_neg(Label,NCover),
10512	intervals_to_list(NCover,NList),
10513	length(NList,N),
10514	asserta(M:'$aleph_search'(coversn,coverns(NCover,N))).
 example_saturated(:Ex:term) is det
Ex is a positive example. This is the current example saturated.

/

10522example_saturated(M:Example):-
10523	example_saturated(Example,M).
10524
10525example_saturated(Example,M):-
10526	M:'$aleph_sat'(example,example(Num,Type)),
10527	M:example(Num,Type,Example).
10528
10529reset(M):-
10530        clean_up(M),
10531	clear_cache(M),
10532	aleph_abolish('$aleph_global'/2,M),
10533	aleph_abolish(example/3,M),
10534	assert(M:example(0,uspec,aleph_false)),
10535	set_default(_,M),
10536	!.
10537
10538% Generic timing routine due to Mark Reid.
10539% Under cygwin, cputime cannot be trusted
10540% so walltime is used instead. To use cputime, set the body of this
10541% predicate to "Time is cputime".
10542stopwatch(Time) :-
10543        Time is cputime.
10544%       statistics(walltime,[Time|_]).
10545
10546wallclock(Time):-
10547	statistics(real_time,[Time|_]).
10548
10549time(P,N,[Mean,Sd]):-
10550        time_loop(N,P,Times),
10551	mean(Times,Mean),
10552	sd(Times,Sd).
10553
10554test_ex(Exs,Flag,N,T,M):-
10555	retractall(M:'$aleph_local'(covered,_)),
10556	retractall(M:'$aleph_local'(total,_)),
10557	asserta(M:'$aleph_local'(covered,0)),
10558	asserta(M:'$aleph_local'(total,0)),
10559    test_ex1(Exs,Flag,M),
10560	retract(M:'$aleph_local'(covered,N)),
10561	retract(M:'$aleph_local'(total,T)).
10562
10563test_ex1(Exs,Flag,M):-
10564	setting(portray_examples,Pretty,M),
10565	member(Example,Exs),
10566	retract(M:'$aleph_local'(total,T0)),
10567	T1 is T0 + 1,
10568	asserta(M:'$aleph_local'(total,T1)),
10569	(once(depth_bound_call(Example,M)) ->
10570		(Flag = show ->
10571			p1_message(covered),
10572			aleph_portray(Example,Pretty,M),
10573			nl;
10574			true);
10575		(Flag = show ->
10576			p1_message('not covered'),
10577			aleph_portray(Example,Pretty,M),
10578			nl;
10579			true),
10580		fail),
10581	retract(M:'$aleph_local'(covered,N0)),
10582	N1 is N0 + 1,
10583	asserta(M:'$aleph_local'(covered,N1)),
10584	fail.
10585
10586test_ex1(_,_,_).
10587
10588
10589
10590test(F,Flag,N,T,M):-
10591	retractall(M:'$aleph_local'(covered,_)),
10592	retractall(M:'$aleph_local'(total,_)),
10593	asserta(M:'$aleph_local'(covered,0)),
10594	asserta(M:'$aleph_local'(total,0)),
10595	(F = [_|_] ->
10596		test_files(F,Flag,M);
10597		test_file(F,Flag,M)
10598	),
10599	retract(M:'$aleph_local'(covered,N)),
10600	retract(M:'$aleph_local'(total,T)).
10601
10602test_files([],_,_M).
10603test_files([File|Files],Flag,M):-
10604	test_file(File,Flag,M),
10605	test_files(Files,Flag,M).
10606
10607test_file('?',_,_M):- !.
10608test_file(File,Flag,M):-
10609	setting(portray_examples,Pretty,M),
10610	aleph_open(File,read,Stream), !,
10611	repeat,
10612	read(Stream,Example),
10613	(Example = end_of_file -> close(Stream);
10614		retract(M:'$aleph_local'(total,T0)),
10615		T1 is T0 + 1,
10616		asserta(M:'$aleph_local'(total,T1)),
10617		(once(depth_bound_call(Example,M)) ->
10618			(Flag = show ->
10619				p1_message(covered),
10620				aleph_portray(Example,Pretty,M),
10621				nl;
10622				true);
10623			(Flag = show ->
10624				p1_message('not covered'),
10625				aleph_portray(Example,Pretty,M),
10626				nl;
10627				true),
10628			fail),
10629		retract(M:'$aleph_local'(covered,N0)),
10630		N1 is N0 + 1,
10631		asserta(M:'$aleph_local'(covered,N1)),
10632		fail),
10633	!.
10634test_file(File,_,_M):-
10635	p1_message('cannot open'), p_message(File).
10636
10637in(false,_,_M):-
10638	!,
10639	fail.
10640in(bottom,Lit,M):-
10641	!,
10642        M:'$aleph_sat'(lastlit,Last),
10643        get_clause(1,Last,[],FlatClause),
10644	aleph_member(Lit,FlatClause).
10645in((Head:-true),Head,_M):- !.
10646in((Head:-Body),L,M):-
10647	!,
10648	in((Head,Body),L,M).
10649in((L1,_),L1,_M).
10650in((_,R),L,M):-
10651	!,
10652	in(R,L,M).
10653in(L,L,_M).
10654
10655in((L1,L),L1,L,_M).
10656in((L1,L),L2,(L1,Rest),M):-
10657	!,
10658	in(L,L2,Rest,M).
10659in(L,L,true,_M).
 random(-X:term, +Dist:term) is det
draw a random number from a distribution /
10666random(X,normal(Mean,Sigma)):-
10667	var(X), !,
10668	normal(Mean,Sigma,X).
10669random(X,normal(_,_)):-
10670	!,
10671	number(X).
10672	% X >= Mean - 3*Sigma,
10673	% X =< Mean + 3*Sigma.
10674random(X,Distr):-
10675	Distr = [_|_],
10676	var(X), !,
10677        draw_element(Distr,X1),
10678	X = X1.
10679random(X,Distr):-
10680	Distr = [_|_],
10681	nonvar(X), !,
10682        aleph_member(Prob-X,Distr), 
10683	Prob > 0.0.
10684
10685mean(L,M):-
10686	sum(L,Sum),
10687	length(L,N),
10688	M is Sum/N.
10689
10690sd(L,Sd):-
10691	length(L,N),
10692	(N = 1 -> Sd = 0.0;
10693		sum(L,Sum),
10694		sumsq(L,SumSq),
10695		Sd is sqrt(SumSq/(N-1) - (Sum*Sum)/(N*(N-1)))).
10696
10697sum([],0).
10698sum([X|T],S):-
10699	sum(T,S1),
10700	S is X + S1.
10701
10702sumsq([],0).
10703sumsq([X|T],S):-
10704	sumsq(T,S1),
10705	S is X*X + S1.
10706
10707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10708% 
10709% auxilliary definitions  for some of the above
10710
10711set_default(A,M):-
10712	default_setting(A,B),
10713	set(A,B,M),
10714	fail.
10715set_default(_,_M).
10716
10717default_setting(A,B):-
10718	set_def(A,_,_,_,B,_),
10719	B \= ''.
10720
10721% special case for threads as only SWI supports it
10722check_setting(threads,B):-
10723	set_def(threads,_,_,Dom,_,_),
10724	check_legal(Dom,B), 
10725	prolog_type(P),
10726	(B > 1 ->
10727		(P = swi -> true;
10728                	err_message(set(threads,B)),
10729                	fail
10730		);
10731		true
10732	), !.
10733check_setting(A,B):-
10734	set_def(A,_,_,Dom,_,_), !,
10735	(check_legal(Dom,B) -> true;
10736		err_message(set(A,B))).
10737check_setting(_,_).
10738
10739check_legal(int(L)-int(U),X):-
10740	!,
10741	number(L,IL),
10742	number(U,IU),
10743	number(X,IX),
10744	IX >= IL,
10745	IX =< IU.
10746check_legal(float(L)-float(U),X):-
10747	!,
10748	number(L,FL),
10749	number(U,FU),
10750	number(X,FX),
10751	FX >= FL,
10752	FX =< FU.
10753check_legal([H|T],X):-
10754	!,
10755	aleph_member1(X,[H|T]).
10756/* AXO: Tolto perche infastidisce e non serve */
10757check_legal(read(filename),X):-
10758	X \= '?',
10759	!,
10760	exists(X).
10761/* il commento finiva qua */
10762
10763check_legal(_,_).
10764
10765number(+inf,Inf):-
10766	Inf is inf, !.
10767number(-inf,MInf):-
10768	MInf is -inf, !.
10769number(X,Y):-
10770	Y is X, !.
10771
10772setting_definition(A,B,C,D,E,F1):-
10773	set_def(A,B,C,D,E,F),
10774	(F = noshow -> F1 = dontshow; F = F1).
10775
10776% set_def(Parameter,Class,TextDescr,Type,Default,Flag)
10777set_def(abduce, search-search_strategy,
10778	'Abduce Atoms and Generalise',
10779	[true, false], false,
10780	show).
10781set_def(best, search-search_space,
10782	'Label to beat',
10783	prolog_term,'',
10784	show).
10785set_def(cache_clauselength, miscellaneous,
10786	'Maximum Length of Cached Clauses',
10787	int(1)-int(+inf), 3,
10788	show).
10789set_def(caching, miscellaneous,
10790	'Cache Clauses in Search',
10791	[true, false], false,
10792	show).
10793set_def(check_redundant, miscellaneous,
10794	'Check for Redundant Literals',
10795	[true, false], false,
10796	show).
10797set_def(check_good, miscellaneous,
10798	'Check good clauses for duplicates',
10799	[true, false], false,
10800	show).
10801set_def(check_useless, saturation,
10802	'Remove I/O unconnected Literals',
10803	[true, false], false,
10804	show).
10805set_def(classes, tree,
10806	'Class labels',
10807	prolog_term,'',
10808	show).
10809set_def(clauselength_distribution, search-search_strategy,
10810	'Probablity Distribution over Clauses',
10811	prolog_term,'',
10812	show).
10813set_def(clauselength, search-search_space,
10814	'Maximum Clause Length',
10815	int(1)-int(+inf), 4,
10816	show).
10817set_def(clauses, search-search_space,
10818	'Maximum Clauses per Theory',
10819	int(1)-int(+inf),'',
10820	show).
10821set_def(condition, evaluation,
10822	'Condition SLP',
10823	[true, false], false,
10824	show).
10825set_def(confidence, tree,
10826	'Confidence for Rule Pruning',
10827	float(0.0)-float(1.0), 0.95,
10828	show).
10829set_def(construct_bottom, saturation,
10830	'Build a bottom clause',
10831	[saturation, reduction, false], saturation,
10832	show).
10833set_def(depth, miscellaneous,
10834	'Theorem Proving Depth',
10835	int(1)-int(+inf), 10,
10836	show).
10837set_def(evalfn, evaluation,
10838	'Evaluation Function',
10839	[coverage, compression, posonly, pbayes, accuracy, laplace,
10840	auto_m, mestimate, mse, entropy, gini, sd, wracc, user], coverage,
10841	show).
10842set_def(explore, search-search_space,
10843	'Exhaustive Search of all alternatives',
10844	[true, false], false,
10845	show).
10846set_def(good, miscellaneous,
10847	'Store good clauses',
10848	[true, false], false,
10849	show).
10850set_def(goodfile, miscellaneous,
10851	'File of good clauses',
10852	write(filename),'',
10853	show).
10854set_def(gsamplesize, evaluation,
10855	'Size of random sample',
10856	int(1)-int(+inf), 100,
10857	show).
10858set_def(i, saturation,
10859	'bound layers of new variables',
10860	int(1)-int(+inf), 2,
10861	show).
10862set_def(interactive, search-search_strategy,
10863	'Interactive theory construction',
10864	[true, false], false,
10865	show).
10866set_def(language, search-search_space,
10867	'Maximum occurrence of any predicate symbol in a clause',
10868	int(1)-int(+inf), +inf,
10869	show).
10870set_def(lazy_negs, evaluation,
10871	'Lazy theorem proving on negative examples',
10872	[true, false], false,
10873	show).
10874set_def(lazy_on_contradiction, evaluation,
10875	'Lazy theorem proving on contradictions',
10876	[true, false], false,
10877	show).
10878set_def(lazy_on_cost, evaluation,
10879	'Lazy theorem proving on cost',
10880	[true, false], false,
10881	show).
10882set_def(lookahead, search-search_space,
10883	'Lookahead for automatic refinement operator',
10884	int(1)-int(+inf), 1,
10885	show).
10886set_def(m, evaluation,
10887	'M-estimate',
10888	float(0.0)-float(+inf),'',
10889	show).
10890set_def(max_abducibles, search-search_space,
10891	'Maximum number of atoms in an abductive explanation',
10892	int(1)-int(+inf), 2,
10893	show).
10894set_def(max_features, miscellaneous,
10895	'Maximum number of features to be constructed',
10896	int(1)-int(+inf), +inf,
10897	show).
10898set_def(minacc, evaluation,
10899	'Minimum clause accuracy',
10900	float(0.0)-float(1.0), 0.0,
10901	show).
10902set_def(mingain, tree,
10903	'Minimum expected gain',
10904	float(0.000001)-float(+inf), 0.05,
10905	show).
10906set_def(minpos, evaluation,
10907	'Minimum pos covered by a clause',
10908	int(0)-int(+inf), 1,
10909	show).
10910set_def(minposfrac, evaluation,
10911	'Minimum proportion of positives covered by a clause',
10912	float(0.0)-float(1.0), 0,
10913	show).
10914set_def(minscore, evaluation,
10915	'Minimum utility of an acceptable clause',
10916	float(-inf)-float(+inf), -inf,
10917	show).
10918set_def(moves, search-search_strategy,
10919	'Number of moves in a randomised local search',
10920	int(0)-int(+inf), 5,
10921	show).
10922set_def(newvars, search-search_space,
10923	'Existential variables in a clause',
10924	int(0)-int(+inf), +inf,
10925	show).
10926set_def(nodes, search-search_space,
10927	'Nodes to be explored in the search',
10928	int(1)-int(+inf), 5000,
10929	show).
10930set_def(noise, evaluation,
10931	'Maximum negatives covered',
10932	int(0)-int(+inf), 0,
10933	show).
10934set_def(nreduce_bottom, saturation,
10935	'Negative examples based reduction of bottom clause',
10936	[true, false], false,
10937	show).
10938set_def(openlist, search-search_space,
10939	'Beam width in a greedy search',
10940	int(1)-int(+inf), +inf,
10941	show).
10942set_def(optimise_clauses, miscellaneous,
10943	'Perform query Optimisation',
10944	[true, false], false,
10945	show).
10946set_def(permute_bottom, saturation,
10947	'Randomly permute order of negative literals in the bottom clause',
10948	[true, false], false,
10949	show).
10950set_def(portray_examples, miscellaneous,
10951	'Pretty print examples',
10952	[true, false], false,
10953	show).
10954set_def(portray_hypothesis, miscellaneous,
10955	'Pretty print hypotheses',
10956	[true, false], false,
10957	show).
10958set_def(portray_literals, miscellaneous,
10959	'Pretty print literals',
10960	[true, false], false,
10961	show).
10962set_def(portray_search, miscellaneous,
10963	'Pretty print search',
10964	[true, false], false,
10965	show).
10966set_def(print, miscellaneous,
10967	'Literals printed per line',
10968	int(1)-int(+inf), 4,
10969	show).
10970set_def(prior, miscellaneous,
10971	'Prior class distribution',
10972	prolog_term,'',
10973	show-ro).
10974set_def(proof_strategy, miscellaneous,
10975	'Current proof strategy',
10976	[restricted_sld, sld, user], restricted_sld,
10977	show).
10978set_def(prooftime, miscellaneous,
10979	'Theorem proving time',
10980	float(0.0)-float(+inf), +inf,
10981	show).
10982set_def(prune_tree, tree,
10983	'Tree pruning',
10984	[true, false], false,
10985	show).
10986set_def(recordfile, miscellaneous,
10987	'Log filename',
10988	write(filename),'',
10989	show).
10990set_def(record, miscellaneous,
10991	'Log to file',
10992	[true, false], false,
10993	show).
10994set_def(refineop, search-search_strategy,
10995	'Current refinement operator',
10996	[user, auto, scs, false],'',
10997	show-ro).
10998set_def(refine, search-search_strategy,
10999	'Nature of customised refinement operator',
11000	[user, auto, scs, false], false,
11001	show).
11002set_def(resample, search-search_strategy,
11003	'Number of times to resample an example',
11004	int(1)-int(+inf), 1,
11005	show).
11006set_def(rls_type, search-search_strategy,
11007	'Type of randomised local search',
11008	[gsat, wsat, rrr, anneal], gsat,
11009	show).
11010set_def(rulefile, miscellaneous,
11011	'Rule file',
11012	write(filename),'',
11013	show).
11014set_def(samplesize, search-search_strategy,
11015	'Size of sample',
11016	int(0)-int(+inf), 0,
11017	show).
11018set_def(scs_percentile, search-search_strategy,
11019	'Percentile of good clauses for SCS search',
11020	float(0.0)-float(100.0),'',
11021	show).
11022set_def(scs_prob, search-search_strategy,
11023	'Probability of getting a good clause in SCS search',
11024	float(0.0)-float(1.0),'',
11025	show).
11026set_def(scs_sample, search-search_strategy,
11027	'Sample size in SCS search',
11028	int(1)-int(+inf), '',
11029	show).
11030set_def(search, search-search_strategy,
11031	'Search Strategy',
11032	[bf, df, heuristic, ibs, ils, rls, scs, id, ic, ar, false], bf,
11033	show).
11034set_def(searchstrat, search-search_strategy,
11035	'Current Search Strategy',
11036	[bf, df, heuristic, ibs, ils, rls, scs, id, ic, ar], bf,
11037	show-ro).
11038set_def(searchtime, search-search_strategy,
11039	'Search time in seconds',
11040	float(0.0)-float(+inf), +inf,
11041	show).
11042set_def(skolemvars, miscellaneous,
11043	'Counter for non-ground examples',
11044	int(1)-int(+inf), 10000,
11045	show).
11046set_def(splitvars, saturation,
11047	'Split variable co-refencing',
11048	[true, false], false,
11049	show).
11050set_def(stage, miscellaneous,
11051	'Aleph processing mode',
11052	[saturation, reduction, command], command,
11053	show-ro).
11054set_def(store_bottom, saturation,
11055	'Store bottom',
11056	[true, false], false,
11057	show).
11058set_def(subsample, search-search_strategy,
11059	'Subsample for evaluating a clause',
11060	[true,false], false,
11061	show).
11062set_def(subsamplesize, search-search_strategy,
11063	'Size of subsample for evaluating a clause',
11064	int(1)-int(+inf), +inf,
11065	show).
11066set_def(temperature, search-search_strategy,
11067	'Temperature for randomised search annealing',
11068	float(0.0)-float(+inf), '',
11069	show).
11070set_def(test_neg, miscellaneous,
11071	'Negative examples for testing theory',
11072	read(filename),'',
11073	show).
11074set_def(test_pos, miscellaneous,
11075	'Positive examples for testing theory',
11076	read(filename),'',
11077	show).
11078set_def(threads, miscellaneous,
11079	'Number of threads',
11080	int(1)-int(+inf), 1,
11081        show).
11082set_def(train_neg, miscellaneous,
11083	'Negative examples for training',
11084	read(filename),'',
11085	show).
11086set_def(train_pos, miscellaneous,
11087	'Positive examples for training',
11088	read(filename),'',
11089	show).
11090set_def(tree_type, tree,
11091	'Type of tree to construct',
11092	[classification, class_probability, regression, model], '',
11093	show).
11094set_def(tries, search-search_strategy,
11095	'Number of restarts for a randomised search',
11096	int(1)-int(+inf), 10,
11097	show).
11098set_def(typeoverlap, miscellaneous,
11099	'Type overlap for induce_modes',
11100	float(0.0)-float(1.0), 0.95,
11101	show).
11102set_def(uniform_sample, search-search_strategy,
11103	'Distribution to draw clauses from randomly',
11104	[true, false], false,
11105	show).
11106set_def(updateback, miscellaneous,
11107	'Update background knowledge with clauses found on search',
11108	[true, false], true,
11109	noshow).
11110set_def(verbosity, miscellaneous,
11111	'Level of verbosity',
11112	int(1)-int(+inf), 1,
11113	show).
11114set_def(version, miscellaneous,
11115	'Aleph version',
11116	int(0)-int(+inf), 5,
11117	show-ro).
11118set_def(walk, search-search_strategy,
11119	'Random walk probability for Walksat',
11120	float(0.0)-float(1.0), '',
11121	show).
11122
11123
11124% the following needed for compatibility with P-Progol
11125special_consideration(search,ida,M):-
11126	set(search,bf,M), set(evalfn,coverage,M), !.
11127special_consideration(search,compression,M):-
11128	set(search,heuristic,M), set(evalfn,compression,M), !.
11129special_consideration(search,posonly,M):-
11130	set(search,heuristic,M), set(evalfn,posonly,M), !.
11131special_consideration(search,user,M):-
11132	set(search,heuristic,M), set(evalfn,user,M), !.
11133
11134special_consideration(refine,Refine,M):-
11135	set(refineop,Refine,M), !.
11136special_consideration(refineop,auto,M):-
11137	gen_auto_refine(M), !.
11138
11139special_consideration(portray_literals,true,M):-
11140	set(print,1,M), !.
11141
11142special_consideration(record,true,M):-
11143	noset(recordfile_stream,M),
11144	(setting(recordfile,F,M) -> 
11145		aleph_open(F,append,Stream),
11146		set(recordfile_stream,Stream,M);
11147		true), !.
11148special_consideration(record,false,M):-
11149	noset(recordfile_stream,M), !.
11150special_consideration(recordfile,File,M):-
11151	noset(recordfile_stream,M), 
11152	(setting(record,true,M) -> 
11153		aleph_open(File,append,Stream),
11154		set(recordfile_stream,Stream,M);
11155		true), !.
11156special_consideration(good,true,M):-
11157	noset(goodfile_stream,M),
11158	(setting(goodfile,F,M) -> 
11159		aleph_open(F,append,Stream),
11160		set(goodfile_stream,Stream,M);
11161		true), !.
11162special_consideration(good,false,M):-
11163	noset(goodfile_stream,M), !.
11164special_consideration(goodfile,File,M):-
11165	noset(goodfile_stream,M), 
11166	(setting(good,true,M) -> 
11167		aleph_open(File,append,Stream),
11168		set(goodfile_stream,Stream,M);
11169		true), !.
11170special_consideration(minscore,_,M):-
11171	aleph_abolish('$aleph_feature'/2,M), !.
11172special_consideration(_,_,_M).
11173
11174rm_special_consideration(portray_literals,_,M):-
11175	set_default(print,M), !.
11176rm_special_consideration(refine,_,M):-
11177	set_default(refineop,M), !.
11178rm_special_consideration(record,_,M):-
11179	noset(recordfile_stream,M), !.
11180rm_special_consideration(recordfile_stream,_,M):-
11181	(setting(recordfile_stream,S,M) -> close(S); true), !.
11182rm_special_consideration(good,_,M):-
11183	noset(goodfile_stream,M), !.
11184rm_special_consideration(goodfile_stream,_,M):-
11185	(setting(goodfile_stream,S,M) -> close(S); true), !.
11186rm_special_consideration(_,_,_M).
11187
11188
11189get_hyp((Head:-Body),M):-
11190	M:'$aleph_search'(pclause,pclause(Head,Body)), !.
11191get_hyp(Hypothesis,M):-
11192        M:'$aleph_global'(hypothesis,hypothesis(_,Hypothesis,_,_)).
11193
11194add_hyp(end_of_file,_M):- !.
11195add_hyp(Clause,M):-
11196        nlits(Clause,L),
11197	label_create(Clause,Label,M),
11198        extract_count(pos,Label,PCount),
11199        extract_count(neg,Label,NCount),
11200        retractall(M:'$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
11201        extract_pos(Label,P),
11202        extract_neg(Label,N),
11203	setting(evalfn,Evalfn,M),
11204	complete_label(Evalfn,Clause,[PCount,NCount,L],Label1,M),
11205        asserta(M:'$aleph_global'(hypothesis,hypothesis(Label1,Clause,P,N))).
11206
11207add_hyp(Label,Clause,P,N,M):-
11208        retractall(M:'$aleph_global'(hypothesis,hypothesis(_,_,_,_))),
11209        asserta(M:'$aleph_global'(hypothesis,hypothesis(Label,Clause,P,N))).
11210
11211add_theory(Label,Theory,PCover,NCover,M):-
11212        aleph_member(C,Theory),
11213	add_hyp(Label,C,PCover,NCover,M),
11214	update_theory(_,M),
11215        fail.
11216add_theory(_,_,PCover,NCover,M):-
11217	rm_seeds(pos,PCover,M),
11218	(setting(evalfn,posonly,M) -> rm_seeds(rand,NCover,M); true),
11219	M:'$aleph_global'(atoms_left,atoms_left(pos,PLeft)),
11220	interval_count(PLeft,PL),
11221	p1_message('atoms left'), p_message(PL), !.
11222
11223add_gcws(M):-
11224	retract(M:'$aleph_search'(gcwshyp,hypothesis(L,C,P,N))),
11225	asserta(M:'$aleph_global'(hypothesis,hypothesis(L,C,P,N))),
11226	update_theory(_,M),
11227	fail.
11228add_gcws(_M).
11229
11230
11231restorehyp(M):-
11232	retract(M:'$aleph_local'(pclause,pclause(Head,Body))),
11233	assertz(M:'$aleph_search'(pclause,pclause(Head,Body))), !.
11234restorehyp(M):-
11235	retract(M:'$aleph_local'(hypothesis,hypothesis(Label,Clause1,P,N))),
11236        asserta(M:'$aleph_global'(hypothesis,hypothesis(Label,Clause1,P,N))), !.
11237restorehyp(_).
11238
11239get_hyp_label(_,Label,_M):- var(Label), !.
11240get_hyp_label((_:-Body),[P,N,L],M):-
11241        nlits(Body,L1),
11242        L is L1 + 1,
11243        (M:'$aleph_search'(covers,covers(_,P))-> true;
11244                        covers(_,M),
11245                        M:'$aleph_search'(covers,covers(_,P))),
11246        (M:'$aleph_search'(coversn,coverns(_,N))-> true;
11247                        coversn(_,M),
11248                        M:'$aleph_search'(coversn,coversn(_,N))).
11249 
11250
11251show_global(Key,Pred,M):-
11252        M:'$aleph_global'(Key,Pred),
11253        copy_term(Pred,Pred1), numbervars(Pred1,0,_),
11254        aleph_writeq(Pred1), write('.'), nl,
11255        fail.
11256show_global(_,_,_M).
11257
11258aleph_portray(hypothesis,true,M):-
11259	M:aleph_portray(hypothesis), !.
11260aleph_portray(hypothesis,false,M):- 
11261	p_message('hypothesis'),
11262	hypothesis(Head,Body,_,M),
11263	pp_dclause((Head:-Body),M), !.
11264aleph_portray(_,hypothesis,_M):-  !.
11265
11266aleph_portray(search,true,M):-
11267	M:aleph_portray(search), !.
11268aleph_portray(search,_,_M):- !.
11269
11270aleph_portray(train_pos,true,M):-
11271	M:aleph_portray(train_pos), !.
11272aleph_portray(train_pos,_,M):-
11273	!,
11274	setting(train_pos,File,M),
11275	show_file(File).
11276
11277aleph_portray(train_neg,true,M):-
11278	M:aleph_portray(train_neg), !.
11279aleph_portray(train_neg,_,M):-
11280	!,
11281	setting(train_neg,File,M),
11282	show_file(File).
11283
11284aleph_portray(test_pos,true,M):-
11285	M:aleph_portray(test_pos), !.
11286aleph_portray(test_pos,_,M):-
11287	!,
11288	setting(test_pos,File,M),
11289	show_file(File).
11290
11291aleph_portray(test_neg,true,M):-
11292	M:aleph_portray(test_neg), !.
11293aleph_portray(test_neg,_,M):-
11294	!,
11295	setting(test_neg,File,M),
11296	show_file(File).
11297
11298aleph_portray(Lit,true,M):-
11299	M:aleph_portray(Lit), !.
11300aleph_portray(Lit,_,_M):-
11301        aleph_writeq(Lit).
11302
11303aleph_writeq(Lit):-
11304	write_term(Lit,[numbervars(true),quoted(true)]).
11305
11306show_file(File):-
11307	aleph_open(File,read,Stream), 
11308	repeat,
11309	read(Stream,Clause),
11310	(Clause = end_of_file -> close(Stream), !
11311		;
11312		writeq(Clause), write('.'), nl,
11313		fail).
11314
11315time_loop(0,_,[]):- !.
11316time_loop(N,P,[T|Times]):-
11317	wallclock(S),
11318        P,
11319	wallclock(F),
11320	T is F - S,
11321        N1 is N - 1,
11322        time_loop(N1,P,Times).
11323
11324list_profile :-
11325        % get number of calls for each profiled procedure
11326        findall(D-P,profile_data(P,calls,D),LP),
11327        % sort them
11328        sort(LP,SLP),
11329        % and output (note the most often called predicates will come last
11330        write_profile_data(SLP).
11331
11332write_profile_data([]).
11333        write_profile_data([D-P|SLP]) :-
11334        % just swap the two calls to get most often called predicates first.
11335        format('~w: ~w~n', [P,D]),
11336        write_profile_data(SLP).
11337 
11338
11339
11340
11341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11342% F I N A L  C O M M A N D S
11343
11344
11345
11346:- multifile sandbox:safe_meta/2.11347
11348sandbox:safe_meta(aleph:induce(_), []).
11349sandbox:safe_meta(aleph:induce_tree(_), []).
11350sandbox:safe_meta(aleph:induce_max(_), []).
11351sandbox:safe_meta(aleph:induce_cover(_), []).
11352sandbox:safe_meta(aleph:induce_incremental(_), []).
11353sandbox:safe_meta(aleph:induce_clauses(_), []).
11354sandbox:safe_meta(aleph:induce_theory(_), []).
11355sandbox:safe_meta(aleph:induce_modes(_), []).
11356sandbox:safe_meta(aleph:induce_features(_), []).
11357sandbox:safe_meta(aleph:induce_constraints(_), []).
11358sandbox:safe_meta(aleph:sat(_), []).
11359sandbox:safe_meta(aleph:aleph_set(_,_), []).
11360sandbox:safe_meta(aleph:aleph_setting(_,_), []).
11361sandbox:safe_meta(aleph:noset(_), []).
11362sandbox:safe_meta(aleph:model(_), []).
11363sandbox:safe_meta(aleph:mode(_,_), []).
11364sandbox:safe_meta(aleph:modeh(_,_), []).
11365sandbox:safe_meta(aleph:modeb(_,_), []).
11366sandbox:safe_meta(aleph:show(_), []).
11367sandbox:safe_meta(aleph:hypothesis(_,_,_), []).
11368sandbox:safe_meta(aleph:rdhyp(_), []).
11369sandbox:safe_meta(aleph:addhyp_i(_), []).
11370sandbox:safe_meta(aleph:sphyp_i(_), []).
11371sandbox:safe_meta(aleph:covers(_), []).
11372sandbox:safe_meta(aleph:coversn(_), []).
11373sandbox:safe_meta(aleph:reduce(_), []).
11374sandbox:safe_meta(aleph:abducible(_), []).
11375sandbox:safe_meta(aleph:bottom(_), []).
11376sandbox:safe_meta(aleph:commutative(_), []).
11377sandbox:safe_meta(aleph:symmetric(_), []).
11378sandbox:safe_meta(aleph:lazy_evaluate(_), []).
11379sandbox:safe_meta(aleph:positive_only(_), []).
11380sandbox:safe_meta(aleph:example_saturated(_), []).
11381
11382sandbox:safe_meta(aleph:addgcws_i(_), []).
11383sandbox:safe_meta(aleph:rmhyp_i(_), []).
11384sandbox:safe_meta(aleph:addgcws_i(_), []).
11385sandbox:safe_meta(aleph:good_clauses(_), [])