/* sample of memu command and output to a file */
% modified: 22 Mar 2003.
% modified: 3 July 2003.
% modified: 7 July 2003.
% modified: 21 Aug 2003. tell_goal/4(forall_such_that), do_by_user_conform/3.
% modified: 8 Aug 2004.  stopwatch and sampling tools to estimate completion time.
% modified: 2 Mar 2005.  testing tools.
% modified: 12 Oct 2005.  tell_goal/2. finalize rule revised.
% modified: 27 Oct 2005.  forall_do_with_displaying_id/2 and total rearrangement of the code.
% modified: 28,31 Oct 2005.  is_there_unspecified/2, do_by_user_conform/3.
% modified: 28,31 Mar 2006.  tell_goal_0/2, tell_goal/2.
% modified: 27 Aug 2006.  close_telling_file/0.
% modified: 4 Feb 2014.  cnt/2.
%---------------------------------------------------%
% Goal repetition counter.
%---------------------------------------------------%
% added: 4 Feb 2014
:- dynamic tmp_goal_cnt/2.
init_cnt:- clause( tmp_goal_cnt(K),_),retract( tmp_goal_cnt(K)), fail.
init_cnt:- !, assert( tmp_goal_cnt(0)).
cnt( Goal, _):-
	 init_cnt,
	 Goal,
	 update_cnt,
	 fail.	
cnt( _, K):-
	 clause( tmp_goal_cnt( K), true).
refcnt( K):-
	 clause( tmp_goal_cnt( K0), true),
	 K is K0 + 1.
update_cnt:-
	 clause( tmp_goal_cnt( K), true),
	 retract( tmp_goal_cnt( K)),
	 J is K + 1, 
	 assert( tmp_goal_cnt( J)),
	 !.
current_cnt( K):-
	 clause( tmp_goal_cnt( K), true),
	 !.
/*
 ?- cnt(member(A,[1,2,3]), K).
K = 3.
 ?- tmp_goal_cnt(I).
I = 3.
*/
%---------------------------------------------------%
% Utilities for user choice menu, display goals,
% and file output
%---------------------------------------------------%
forall_write(A):- forall(member(X,A),(nl,write(X))).
forall_write_goals(A,B):- B,nl,write(A),fail.
forall_write_goals(_,_):- nl,write(complete).
% verify unspecified.
% added: 28 Oct 2005. (from impl13b.pl)
 
is_there_unspecified( No, User):- 
   \+ ( member(X,User),var(X)),
   !,
   No=no.
is_there_unspecified( yes, _).
% display all successful goals (with the count).
display_goals(G):-
   (\+ var(G)->true;G=empty),
   forall(G,(nl,write(G))).
display_goals(_).
display_goals(G,C):-
   (\+ var(G)->true;G=empty),
   (\+ var(C)->true;C=true),
   forall((G,C),(nl,write(G))).
display_goals(_,_).
display_goals(G,C,N):-
   (\+ var(G)->true;G=empty),
   (\+ var(C)->true;C=true),
   findall(G,(G,C),L),
   length(L,N),
   display_goals(G,member(G,L)),
   nl,
   write('the number of goals='),
   write(N).
%  save the successful goal into a specified text file.
%---------------------------------------------------%
% revised: 12 Oct 2005, 28,31 Mar 2006. 
tell_goal_0(File,G):-
   open(File,write,_S),
   tell(File),
   nl,
   tstamp('% file output start time ',_),
   nl,
   write('%----------  start from here ------------%'),
   nl,
   G,
   nl,
   write('%----------  end of data ------------%'),
   nl,
   tstamp('% file output end time ',_),
   tell(user),
   current_stream(File,write,S0),
   close(S0).
tell_goal(File,G):-
   forall(current_stream(File,write,S0),close(S0)),
   tell_goal_0(File,G),
   forall(current_stream(File,write,S0),close(S0)),
   write(complete).
% 成功するゴールをすべて保存
% save all successful goals to file.
%---------------------------------------------------%
tell_goal(File,forall,G):-
   G0 = (nl,write(G),write('.')),
   G1 = forall(G,G0),
   tell_goal(File,G1).
% the conditionalized version
% Aug 2003.
tell_goal(File,forall_such_that,G,Condition):-
   % G should be occurred in the Condition.
   WRITE = (nl,write(G),write('.')),
   G1 = forall(Condition,WRITE),
   tell_goal(File,G1).
% close stream
%---------------------------------------------------%
close_telling_file:-
   current_stream(A,write,B),
   \+ member( A, [1,2]),
   nl(user),write(user,'close ':A:'? (y):'),
   read(y),
   close(B),
   nl,write('closed.'),
   fail.
close_telling_file:-
   nl,
   write('no more.').
% 実行時刻の取得
% time stamp
%---------------------------------------------------%
tstamp(no,T):-
   get_time(U),
   convert_time(U,A,B,C,D,E,F,_G),
   T = [date(A/B/C), time(D:E:F)],
   nl.
tstamp(Word,T):-
   \+ var(Word),
   Word \= no,
   get_time(U),
   convert_time(U,A,B,C,D,E,F,_G),
   T = [date(A/B/C), time(D:E:F)],
%   format('~`.t~t~a~30|~`.t~t~70|~n',[Word]),
   write((Word,T)),
   nl.
%  stopwatch
%---------------------------------------------------%
% added: 24 Feb 2004. (cited from: beleq03.pl)
% modified: 8 Mar 2004.
stopwatch_0(Goal,TD):-
   get_time(TS),
   Goal,
   get_time(TF),
   TD is TF - TS.
stopwatch(Goal,TD):-
   stopwatch_0(Goal,TD),   
   nl,
   write('% time elapsed (sec): '),
   write(TD),
   nl.
stopwatch_of_iterated_goals(_Goal,0,0,Display):-
   rule_of_display_number_in_stopwatch(Display,JOB),
   JOB.
stopwatch_of_iterated_goals(Goal,TD,Iteration,Display):-
   number(Iteration),
   Iteration > 0,
   init_count_of_display,
   rule_of_display_number_in_stopwatch(Display,JOB),
   stopwatch(
     forall(
      (
       Goal, %write(Goal),
       update_count_of_display(K),
       (K>Iteration->!,fail;true)
      ),
       JOB
     ),
     TD
   ).
rule_of_display_number_in_stopwatch(no,true):-
   !.
rule_of_display_number_in_stopwatch(yes,display_counter).
% a display of counter for iterated goals.
%---------------------------------------------------%
% added: 22 Feb 2004.
% modified: 8--9 Mar 2004. minor bugfix.
:- dynamic temp_count_of_display/1.
temp_count_of_display(0).
init_count_of_display:-
   abolish(temp_count_of_display/1),
   assert(temp_count_of_display(0)).
update_count_of_display(K):-
   retract(temp_count_of_display(K0)),
   K is K0 + 1,
   assert(temp_count_of_display(K)).
update_and_display_counter:-
   update_count_of_display(_),
   display_counter.
display_counter:-
   temp_count_of_display(K),
   nl,
   write([K]).
% a sampling tool for estimating time complexity.
%---------------------------------------------------%
% added: 8--9 Mar 2004. (cited from: beleq03.pl)
get_average_time_by_sampling(H/LA,N,((SampleTime + TotalTime) / N)=AverageTime):-
   length(A,LA),
   Goal=..[H|A],
   stopwatch_0(Goal,SampleTime),
   rule_for_decide_number_of_trials(Goal,SampleTime,N),
   (N = 0 -> !,fail; true),
   N1 is N - 1,
   length(B,LA),
   Goal1=..[H|B],
   stopwatch_of_iterated_goals(Goal1,TotalTime,N1,no),
   AverageTime is (SampleTime + TotalTime) / N,
   !.
   
rule_for_decide_number_of_trials(_,_,Trials):-
   integer(Trials).  % conform to user.  
rule_for_decide_number_of_trials(_,SampleTime,20):-
   SampleTime=<1.
rule_for_decide_number_of_trials(_,SampleTime,10):-
   SampleTime>1,
   SampleTime=<5.
rule_for_decide_number_of_trials(_,SampleTime,3):-
   SampleTime>5,
   SampleTime=<10.
rule_for_decide_number_of_trials(_,SampleTime,1):-
   SampleTime>10.
% for debug:
check_if_false(_,G):-
   G,!.
check_if_false(A,_G):-
   nl, write('**** fail ****'),write(A),
   nl, write('continue ? > '),read(y).
% displaying goals with update id numbers:
% an alternative for display_goals/1,2,3 
%---------------------------------------------------%
% added: 27 Oct 2005 (cited from: impl13b.pl)
forall_do_with_displaying_id( G,M):-
   init_count_of_display,
   forall( G,
    (
     update_and_display_counter,
     tab(1),
     write(M)
    )
   ).
% save all predicates to file 
%---------------------------------------------------%
% cited from: impl12.pl(Jan 2003, added: 24 Sep 2002)
% modified and added: 3 June 2003.
tell_all_pred:-
   Q=user_defined_predicate(P,Info),
   G1=findall((P,Info),Q,D),
   G2=forall(
     (
      member((P,Info),D)
     ),
     (
      P=..[X|Z],
      %current_functor(X,Y)
      length(Z,L),
      write(X),write(' / '),
      write(L),tab(2),write(Info),nl
     )
   ),
   G=(G1,G2),
   tell_goal('all_pred.txt',G).
% added: 3 June 2003.
user_defined_predicate(P,[file(F),lines(L),clauses(N)]):-
    predicate_property(P,line_count(L)),
    predicate_property(P,number_of_clauses(N)),
    predicate_property(P,file(F)),
    \+ predicate_property(P,imported_from(system)),
    \+ predicate_property(P,built_in).
% pretty print of the arities of the successful goal. 
%-----------------------------------------
% added: 7 July 2003. (cited from: networ0.pl)
ppf(Functor):-
   Functor=..[G|X],
   nl,
   write(functor:G),
   forall(member(Z,X),(nl,tab(2),write(Z))).
ppg(Goal):-
   Goal=..[G|X],
   Goal,
   nl,
   write(goal:G),
   forall(member(Z,X),(nl,tab(2),write(Z))).
ppl([Head|List]):-
   nl,
   write(Head),
   forall(member(Z,List),(nl,tab(2),write(Z))).
% predicate equivalence cited from kalp01
%---------------------------------------------------%
% added : 2 Mar 2005.
verify_equality_of_goals(G1:V1,G2:V2,S,D):-
   findall(V1,G1,S1),
   findall(V2,G2,S2),
   subtract(S1,S2,D1),
   subtract(S2,S1,D2),
   S=[S1,S2],D=[D1,D2].
% a script for generating goals as facts
%---------------------------------------------------%
:- dynamic id_of_temp_goal/1.
:- dynamic temp_goal/3.
update_id_of_temp_goal(ID):-
   retract(id_of_temp_goal(ID_0)),
   ID is ID_0 +1,
   assert(id_of_temp_goal(ID)).
preliminary_to_factualize_goals:-
   abolish(id_of_temp_goal/1),
   abolish(temp_goal/3),
   assert(id_of_temp_goal(0)).
factualize_goals(G):-
   warn_if_not_a_list(G),
   preliminary_to_factualize_goals,
   factualize_goals(G,LID),
   finalize_factualization(LID).
factualize_goals([Goal|Constraint],ID):-
   Goal,
   Constraint,
   update_id_of_temp_goal(ID),
   assert(temp_goal(ID,Goal,Constraint)),
   fail.
factualize_goals(_,ID):-
   id_of_temp_goal(ID).
finalize_factualization(Last_ID):-
   write(complete),
   nl,
   write(total:Last_ID),
   write(' successful goals have asserted as temp_goal/3.').
warn_if_not_a_list(G):-
   length(G,_),
   forall(member(X,G),clause(X,_)),
   !.
warn_if_not_a_list(_):-
   write('**** warning : not a list of executable goals.'),
   nl,
   write('no data has generated.'),
   fail.
%  a multiple-choice menu 
%---------------------------------------------------%
menu(A,N,B):-
   choice_menu1(A,N),
   clause(A,B),
   numbervars([A,B],f,1,_E).
choice_menu1(A,N):-
% write(helllo),
   setof(B,A0^current_predicate(A0,B),Bs),
% write(Bs),
   setof([K,A/L,B],
     B^C^K1^(
       nth1(K1,Bs,B),
       K_min is 10,
      %nth1(K_min,Bs,write(_)),
       K1 > K_min,
       K is K1 - K_min,
       B=..[A|C],
% write(B),
      length(C,L)
     ),
   Menu),
   forall(
     member( [U,A,_],Menu),
     (tab(1),write([U,A]),nl)
   ),
   tab(3),
   write(number),
   read(U),
   (
    member( [U,_,B], Menu)
     ->
       (N=U,A=B)
     ;
       choice_menu1(A,N)
   ).
choice_menu2(A,N,Menu,Bag):-
   \+ var( Menu),
   Msg='正しく番号を入力し、ピリオドを打ってください。',
  (
   display_each( Menu),
   (
    read(U),
    nth1( U,Menu,B))
    ->(
      A = B, U = N, write(A), nl
     )
    ;(
      write( Msg), nl, choice_menu1(A,Bag)
     )
  ).
display_each(Bag):-
   forall(
     nth1( K,Bag,B1),
     (write(K),write('.'),write(B1),nl)
   ).
%  user conform 
%---------------------------------------------------%
do_by_user_conform(if(USER),then(ACT1),else(ACT2)):-
   (var(USER)->read(USER);true),
   (
    member(USER,
      [y,'Y',yes,'Yes','YES',ok,'OK',go]
    )
     -> ACT1  ;  ACT2
   ).