#! /usr/bin/swipl
% (home + travail)

% #! /usr/local/swipl/bin/swipl
% (magi)

/* ========================================================================== */ 
/*                            CREATE TRAIN AND TEST FILES                     */
/*                        (used in a context of a cross validation)           */
/* ========================================================================== */

:- set_prolog_flag(verbose, silent).
												% stacks
:- set_prolog_stack(local,  limit(10**9)).  	% 1 Go
:- set_prolog_stack(global, limit(10**9)).	
:- set_prolog_stack(trail,  limit(10**9)).

:- initialization goal.

/* ========================================================================== */

goal :-
        get_arguments(File_int, File_train, File_test, Fold, Nb_fold),
	   create_train_test_files(File_int, File_train, File_test, Fold, Nb_fold),
	   halt(0).
 
get_arguments(File_int, File_train, File_test, Fold, Nb_fold) :-
        current_prolog_flag(argv, Argv),
        append(_, [File_int, File_train, File_test, Fold1, Nb_fold1], Argv),
	   atom_number(Fold1, Fold),
	   atom_number(Nb_fold1, Nb_fold).



   /* create a file containing positive and negative examples */
create_train_test_files(
                         File_in,    % file containing intensional complete examples
			          File_train, % file that will contain (complete) train examples
				     File_test,  % file that will contain test examples 
                         K,          % number of the current fold
                         N           % nb fold                       
                      ) :-    
   init_modules,
   writeln('building train test files examples...'),
   create_files(File_in, File_train, File_test, K, N),
   writeln('finished').


init_modules :-         

   getenv('LEAR_DIR', Lear),
   
   atom_concat(Lear, '/file.pl', File),
   use_module(File),

   atom_concat(Lear, '/counter.pl', Counter),
   use_module(Counter),  

   atom_concat(Lear, '/list.pl', List),
   use_module(List),

   atom_concat(Lear, '/intentional_data.pl', Int_data),
   use_module(Int_data).


/* ============================== GETTING EXAMPLES ========================== */

get_positive_examples(LPos) :-
   findall(
            (pos, Ex, Domains, Target), 
            (ex:pos(N,Ex), 
             ex:target(N, pos, Target), 
             ex:domains(N, pos, Domains)),
            LPos
           ).
   
get_negative_examples(LNeg) :-
   findall(
            (neg, Ex, Domains, Target), 
            (
              ex:neg(N,Ex), 
              ex:target(N, neg, Target), 
              ex:domains(N, neg, Domains)
            ),
            LNeg
           ).
   
/* ========================= CREATING EXAMPLES ============================== */  

create_files(File_in, File_train, File_test, K, N) :-

   consult_intentional_examples(ex, File_in),
   get_positive_examples(LPos),
   get_negative_examples(LNeg),

   atom_concat(File_train, '.int', File_train1),
   open(File_train1, write, Stream_train),

   atom_concat(File_test, '.int', File_test1), 
   open(File_test1, write, Stream_test),
   
   fwrite_ln(Stream_train, ':- style_check(-discontiguous).'),
   nl(Stream_train),
   
   fwrite_ln(Stream_test, ':- style_check(-discontiguous).'),
   nl(Stream_test),
   
   reset_count(nb_examples_train),
   reset_count(nb_examples_test),

   deal_with_examples(LPos, K, N, Stream_train, Stream_test),

   reset_count(nb_examples_train),
   reset_count(nb_examples_test),

   deal_with_examples(LNeg, K, N, Stream_train, Stream_test),
  
   close(Stream_train),
   close(Stream_test).
   

	/* build a set of train examples and a set of test examples */
deal_with_examples(Lex, K, N, Stream_train, Stream_test) :-
   length(Lex, Nex),
   Ntest is Nex/N,

   compute_indices(K, N, Nex, Ntest, 
                   Begin_test, End_test, Begin_train1, End_train1,
                   Begin_train2, End_train2),

   
   get_interval_examples(Lex, Begin_test, End_test, LTest),
   get_interval_examples(Lex, Begin_train1, End_train1, LTrain1),
   get_interval_examples(Lex, Begin_train2, End_train2, LTrain2),
   append(LTrain1, LTrain2, LTrain),

   write_examples(train, LTrain, Stream_train),
   write_examples(test, LTest, Stream_test).

   
	/* computes indices of test and train examples */
	
	% first fold
 compute_indices(
                  1,                    % first fold
			   	  _N,                    % nb folds
			         Nex,                  % nb examples
                  Ntest,                % nb test examples
                  1, 					    % begin test	 		
                  End_test,             % end test
                  Begin_train1, 
			         End_train1,
                 -1,                    % fictive value 
                 -2                     % fictive value
                ) :-
   !,								            
  End_test is floor(Ntest),
  Begin_train1 is End_test + 1,
  End_train1 is Nex.
 
 	% last fold
 compute_indices(
                  N, 				% last fold
                  N, 				% nb folds
                  Nex, 				% nb examples
                  Ntest, 			% nb examples test
                  Begin_test, 			
                  Nex, 				% end test
                  1,             % begin Train 1
                  End_train1,
                  -1, 				% fictive value
                  -2				   % fictive value
                ) :- 
   !,							% last fold   
   End_train1 is floor((N-1) * Ntest),
   Begin_test is End_train1 + 1.

	% neither first nor last fold
compute_indices(
                  K, 				     % current fold
                  _N, 				     % nb folds
                  Nex, 				     % nb examples
                  Ntest, 			     % nb examples test
                  Begin_test, 			
                  End_test, 
                  1,                  % begin train1 
                  End_train1,
                  Begin_train2, 
                  Nex                 % end train2
               ) :-
  End_train1 is floor((K-1) * Ntest),
  Begin_test is End_train1 + 1,
  End_test is floor(K*Ntest),
  Begin_train2 is End_test + 1.
  

get_interval_examples(_Lex, Deb, End, []) :-
   Deb > End,
   !.

get_interval_examples(Lex, N, End, [Ex|LEx1]) :-
   nth1(N, Lex, Ex),
   N1 is N+1,
   get_interval_examples(Lex, N1, End, LEx1).
   

/* ============================ WRITING THE EXAMPLES ======================== */

write_examples(_Test_train, [], _Stream) :-
   !.

write_examples(Test_train, [Ex|LEx], Stream) :-
   write_one_example(Test_train, Ex, Stream),
   write_examples(Test_train, LEx, Stream).
      
      
	/* write the current example */ 
write_one_example(Train_test, (Signe, Ex, Domain, Target), Stream) :-
  get_new_example_number(Train_test, N),
  Term =..[Signe, N, Ex],
  fwrite_point_ln(Stream, Term),
  fwrite_point_ln(Stream, target(N, Signe, Target)),
  fwrite_point_ln(Stream, domains(N, Signe, Domain)),
  nl(Stream).
              
           
get_new_example_number(train, N) :-
   !,
   get_count(nb_examples_train, N).
   
get_new_example_number(test, N) :-
   get_count(nb_examples_test, N).
   
/* ============================== END OF LISTING ============================ */   
