/* ========================================================================== */ 
/*                           GET/SET INTENTIONAL DATA                         */
/* ========================================================================== */

:- module(intentional_data,
          [

						/* ============== read/write examples ========= */	

		   consult_intentional_examples/2,
                              % (Module, File)

		   read_intentional_examples/4,
						% (Module, File, LPos, LNeg)

		   read_intentional_examples/3,
						% (File, LPos, LNeg)

		   write_intentional_examples/3,   
                              %(File, LPos, LNeg)

             write_intentional_example/4,
					       % Ex, 	      an ambiguous example
                                % Label,      its label (pos or neg)
                                % N,          its identifier (integer)
                                % Stream      Stream where to write it

		   write_intentional_example_domain_target/4,
					       %  Ex, 	       an ambiguous example
                                %  Label, 	  its label (pos or neg)
                                %  N,          its identifier (integer)
                                %  Stream      Stream where to write it

		   write_intentional_examples_domains_targets/4,
                                % N,              numbering examples from N
					       % Lex, 	          list of examples
                                % Label, 	     label (pos or neg) of examples
                                % Stream          Stream where to write
              			
						/* ========== background knowledge ======== */
                                
		    get_target_relation/2,
		                      % (Module, Target_relation)
		
              get_target_mode/2,
                                % (Module, Target_mode)

		    get_modes/2,
                                % (Module, LModes)

		    get_modes_atoms/2,
						  % (Module, LModes_atoms)

		    get_types_under_oi/2, 
                                % (Module, Types_under_oi)
 
		    get_non_abducible_predicates/2,
			                 % (Module, Non_abducible)

		    get_irrelevant/2,
		                      % (Module, L)
            
              get_clauses_background/2,
			                 % (Module, LClauses_bkg)

              consult_background_knowledge/2,
                                % (Module, File_bkg)

		    read_intentional_background/10,
                                % (Module, File_bkg, 
                                %  Target_relation, Target_mode,
                                %  LModes, Types_instantiable,
                                %  Types_under_oi, Non_abducible, 
                                %  LIrrelevant, LClauses_bkg)

		    write_intentional_background_knowledge/9,
						 % File_out, Target, Target_mode, LModes, 
                               % Types_instantiable,Types_under_oi,
                               % Non_abducible,LIrrelevant, LBackground),	

		    discard_plus_minus/2,
                                % (LArgs, LArgs1)  
                                % LArgs1 have no longer '+' prefixes

		    discard_plus_minus_args/2,

		   				/* ================= operators ================ */
		    initialization_op/1,
		    initialization_op/0

						/* =========== MISCELANEOUS =================== */

		   
           ]).

/* ============================= DIRECTIVES ================================= */

:- getenv('LEAR_DIR', Lear),

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

   atom_concat(Lear, '/term.pl', Term),
   use_module(Term),

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

/* =========================== BACKGROUND_KNOWLEDGE ========================= */

read_intentional_background(Module, File_bkg, 
                            Target_relation, Target_mode,
                            LModes, Types_instantiable,
                            Types_under_oi, Non_abducible, 
                            LIrrelevant, LClauses_bkg) :-
	initialization_op(Module),
	consult_background_knowledge(Module, File_bkg),
	get_target_relation(Module, Target_relation),
	get_target_mode(Module, Target_mode),
     get_modes(Module, LModes),
	get_types_instantiable(Module, Types_instantiable),
	get_types_under_oi(Module, Types_under_oi),
	get_non_abducible_predicates(Module, Non_abducible),
	get_irrelevant(Module, LIrrelevant),
	get_clauses_background(Module, LClauses_bkg).

get_target_relation(Module, Target_relation) :-
   Module:target_relation(Target_relation).


get_target_mode(Module, Target_mode) :-
   Module:target_mode(Target_mode).


get_modes(Module, LModes) :-
     findall(Mode, Module:mode(Mode), LModes).

get_modes_atoms(Module, LModes_atoms) :-
	findall(mode(Mode), Module:mode(Mode), LModes_atoms).


get_types_instantiable(Module, Types_instantiable) :-
   Module:types_instantiable(Types_instantiable).


get_types_under_oi(Module, Types_under_oi) :-
   Module:types_under_oi(Types_under_oi).


get_non_abducible_predicates(Module, Non_abducible) :-
   Module:non_abducible_predicates(Non_abducible).


get_irrelevant(Module, L) :-
   Module:irrelevant(L1),
   refresh_list(L1, L).


get_irrelevant(LIrrelevant) :-
   get_irrelevant(intentional, LIrrelevant).


get_clauses_background(Module, LClauses_bkg) :-
   Module:background_knowledge(LClauses),
   refresh_list(LClauses, LClauses_bkg).


	/* consult File_bkg into Module */
consult_background_knowledge(Module, File_bkg) :-
	atom_concat(File_bkg, '.int_bkg', File_bkg_int),
     initialization_op(Module),
     Module:consult(File_bkg_int).


write_intentional_background_knowledge(
                                       File, Target, Target_mode, LModes, 
                                       Types_instantiable,Types_under_oi,
                                       Non_abducible, LIrrelevant, LBackground
                                      ) :-

	atom_concat(File, '.int_bkg', File_int_bkg),
	open(File_int_bkg, write, Out),
     
	make_variables_syntactically_anonymous(Target, Target1),
	fwrite_point_ln(Out, target_relation(Target1)),
	fwrite_point_ln(Out, target_mode(Target_mode)),
	nl(Out),

	build_modes_atoms(LModes, LModes_atoms),
	fwrite_list_atoms(Out, LModes_atoms),

	nl(Out),

	fwrite_point_ln(Out, types_instantiable(Types_instantiable)),
	fwrite_point_ln(Out, types_under_oi(Types_under_oi)),
	fwrite_point_ln(Out, non_abducible_predicates(Non_abducible)),
	fwrite_point_ln(Out, irrelevant(LIrrelevant)),

	nl(Out),

	fwrite_ln(Out,'background_knowledge('),
	fwrite_list_numbervars(Out, LBackground),
	fwrite_point_ln(Out, ')'), 
	
	close(Out).


/* =====================  READ/ WRITE INTENTIONAL EXAMPLES ================== */

consult_intentional_examples(Module, File) :-
   atom_concat(File, '.int', File1),
   Module:consult(File1).


	/* get examples, modes and background knowledge */
read_intentional_examples(Module, File, LPos, LNeg) :-       
        consult_intentional_examples(Module, File),
	   get_positive_examples_domains_targets(Module, LPos),
        get_negative_examples_domains_targets(Module, LNeg).


read_intentional_examples(File, LPos, LNeg) :-
	read_intention_examples(intentional, File, LPos, LNeg).


 write_intentional_examples(File, LPos, LNeg) :-
   atom_concat(File, '.int', File_out),
   open(File_out, write, Out),
 
   write(Out, ':- style_check(-discontiguous).'),
   nl(Out),
         							
   write_intentional_examples_domains_targets(1, LPos, pos, Out),
   write_intentional_examples_domains_targets(1, LNeg, neg, Out),
                         
   close(Out).


	/* write an intentional ambiguous example */ 
write_intentional_example(
					  Ex, 		% an ambiguous example
                           Label, 	     % its label (pos or neg)
                           N,           % its identifier (integer)
                           Stream       % Stream where to write it
                          ) :-
   write(Stream, Label),
   write(Stream,'('),
   write(Stream, N),
   write(Stream,','),
   nl(Stream),
   fwrite_list(Stream, Ex),
   write(Stream,')'),
   write(Stream, '.'),
   nl(Stream).


   /* write a list of intentional ambiguous examples */
write_intentional_examples_domains_targets(
                           N,                % numbering examples from N
					  LEx, 			% list of examples
                           Label, 			% label (pos or neg) of examples
                           Stream            % Stream where to write
                          ) :-
   write_numbered_intentional_examples_domains_targets(LEx, N, Label ,Stream).



	/* write a list of intentional ambiguous example */
write_numbered_intentional_examples_domains_targets([], _Num, _Label, _Stream) :-
   !.

	/* write a list of intentional ambiguous example */
write_numbered_intentional_examples_domains_targets([Ex|LEx], Num, Label, Stream) :-
   write_intentional_example_domain_target(Ex, Label, Num, Stream),
   Num1 is Num+1,
   write_numbered_intentional_examples_domains_targets(LEx, Num1, Label, Stream).


	/* write an intentional ambiguous example */ 
write_intentional_example_domain_target(
					  (Ex,Domain,Target),  % an ambiguous example
                           Label, 			      % its label (pos or neg)
                           N,                   % its identifier (integer)
                           Stream               % Stream where to write it
                          ) :-
  write_intentional_example(Ex, Label, N, Stream),
  nl(Stream),
  Term_domain=..[domains, N, Label, Domain],
  fwrite_point_ln(Stream, Term_domain),
  Term_target=..[target, N, Label, Target],
  fwrite_point_ln(Stream, Term_target),
  nl(Stream).


/* ============================= GET INTENTIONAL EXAMPLES =================== */ 

get_positive_examples_domains_targets_old(LPos) :-  % examples are clauses
   findall(
            (Pos, Domains, Target),
            (
              intentional:pos(N, Pos),
              intentional:domains(N,  Domains),
              intentional:target(N, Target)
            ),
            LPos
           ).

get_positive_examples_old(LPos, []) :-
   findall(
            (Pos, Domains),
            (
              intentional:pos(N, Pos),
              intentional:domains(N, Domains)
            ),
            LPos
           ).

get_negative_examples_domains_targets_old(LNeg) :-  % examples are clauses

   findall(
            (Neg, Domains, Target),
            (
              intentional:neg(N, Neg),
              intentional:domains(N, Domains),
              intentional:target(N, Target)
            ),
            LNeg
           ).

get_negative_examples_old(LNeg, []) :-
   findall(
            (Neg, Domains),
            (
              intentional:neg(N, Neg),
              intentional:domains(N, Domains)
            ),
            LNeg
           ).


get_positive_examples_domains_targets(Module, LPos) :-  % examples are clauses
   findall(
            (Pos, Domains, Target),
            (
              Module:pos(N, Pos),
              Module:domains(N, pos, Domains),
              Module:target(N, pos, Target)
            ),
            LPos
           ).


get_positive_examples_domains_targets(LPos) :-  % examples are clauses
   findall(
            (Pos, Domains, Target),
            (
              intentional:pos(N, Pos),
              intentional:domains(N, pos, Domains),
              intentional:target(N, pos, Target)
            ),
            LPos
           ).


get_positive_examples(Module, LPos, []) :-
   findall(
            (Pos, Domains),
            (
              Module:pos(N, Pos),
              Module:domains(N, pos, Domains)
            ),
            LPos
           ).


get_positive_examples(LPos, []) :-
   findall(
            (Pos, Domains),
            (
              intentional:pos(N, Pos),
              intentional:domains(N, pos, Domains)
            ),
            LPos
           ).


get_negative_examples_domains_targets(Module, LNeg) :-  % examples are clauses
   findall(
            (Neg, Domains, Target),
            (
              Module:neg(N, Neg),
              Module:domains(N, neg, Domains),
              Module:target(N, neg, Target)
            ),
            LNeg
           ).

get_negative_examples_domains_targets(LNeg) :-  % examples are clauses

   findall(
            (Neg, Domains, Target),
            (
              intentional:neg(N, Neg),
              intentional:domains(N, neg, Domains),
              intentional:target(N, neg, Target)
            ),
            LNeg
           ).


get_negative_examples(Module, LNeg, []) :-
   findall(
            (Neg, Domains),
            (
              Module:neg(N, Neg),
              Module:domains(N, neg, Domains)
            ),
            LNeg
           ).


get_negative_examples(LNeg, []) :-
   findall(
            (Neg, Domains),
            (
              intentional:neg(N, Neg),
              intentional:domains(N, neg, Domains)
            ),
            LNeg
           ).

/* ================================ OPERATORS ================================ */

        /* declare the needed operators in the module intentional */
initialization_op(Module) :-
        Module:(op(900, xfy, <=)),
        Module:(op(900, xfy, <-)),
        Module:(op(900, fx, <-)),
        Module:(op(850, xfy, or)),
        Module:(op(850, xfy, and)).

initialization_op :-
	initialization_op(intentional).


/* ========================= MISCELLANEOUS ==================================== */

build_modes_atoms([], []) :-
   !.

build_modes_atoms([Mode|LModes], [mode(Mode) |LModes_atoms]) :-
   build_modes_atoms(LModes, LModes_atoms).


		/* discard + or - as prefix of atoms in the the mode declarations */
discard_plus_minus([], []) :-
   !.

discard_plus_minus([Mode|LModes], [Mode1|LModes1]) :-
   discard_plus_minus_one_mode(Mode, Mode1),
   discard_plus_minus(LModes, LModes1).


discard_plus_minus_one_mode(Mode, Mode1) :-
   Mode=..[Pred|LArgs],
   discard_plus_minus_args(LArgs, LArgs1),
   Mode1=..[Pred|LArgs1].


discard_plus_minus_args([], []) :-
   !.

discard_plus_minus_args([Arg|LArgs], [Arg1|LArgs1]) :-
   discard_plus_minus_one_arg(Arg, Arg1),
   discard_plus_minus_args(LArgs, LArgs1).


discard_plus_minus_one_arg(+Arg, Arg) :-
   !.

discard_plus_minus_one_arg(-Arg, Arg) :-
   !.

discard_plus_minus_one_arg(Arg, Arg).


/* ============================== END OF LISTING ============================ */

