%% Copyright (C) 2012 Igor Stéphan
%% 
%% This program is free software; you can redistribute it and/or
%% modify it under the terms of the GNU General Public License
%% as published by the Free Software Foundation; either version 2
%% of the License, or (at your option) any later version.
%% 
%% This program is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%% GNU General Public License for more details.
%% 
%% You should have received a copy of the GNU General Public License
%% along with this program; if not, write to the Free Software
%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
%% http:%%www.gnu.org/copyleft/gpl.html
%%
%% igor.stephan@univ-angers.fr
%% 
:- module('ITERATIVE_COMPILATION', [construit_bl/3]).
:- use_module(library(lists)).
:- use_module('ITERATIVE_CONSTRUCTION', [empty_bl/2,insert_bl_from_stock/3]).

construit_bl(Quant, Trace, bl(Facteurs)) :-
	empty_bl(Quant, Facteurs_Vide),
	QuantSuiv =  Quant,
	QuantPred = [],
	Branche = [],
	descente(Trace, Branche, QuantPred, QuantSuiv, [], flot(Facteurs_Vide, Facteurs)).



descente([branch(X, Val) | Trace], Branche, QuantPred, [Q | QuantSuiv], Stock, Flot_Facteurs) :-
	(Q = a(X_, _D_X) ; Q = e(X_, _D_X)), X == X_, % Uniquement pour les tests
	QuantPred_ = [Q | QuantPred],
	descente(Trace, [(X,Val) | Branche], QuantPred_, QuantSuiv, Stock, Flot_Facteurs).

descente([succes | Trace], Branche, QuantPred, [], Stock, Flot_Facteurs) :-
	Stock_ = [Branche | Stock],
	backtrack(Trace, Branche, QuantPred, [], Stock_, Flot_Facteurs).

descente([echec | Trace], Branche, QuantPred, QuantSuiv, Stock, Flot_Facteurs) :-
	backtrack(Trace, Branche, QuantPred, QuantSuiv, Stock, Flot_Facteurs).

backtrack([], _Branche, _QuantPred, _QuantSuiv, _Stock, flot(Facteurs, Facteurs)) :-
	!.


backtrack([echec(U, _Val_U) | Trace], Branche_In, QuantPred, QuantSuiv, Stock, Flot_Facteurs) :-
	!,
	destocke_universelle(U, Branche_In, Branche_Out, QuantPred, QuantSuiv, QuantPred_, QuantSuiv_, Stock, Stock_),
	backtrack(Trace, Branche_Out, QuantPred_, QuantSuiv_, Stock_, Flot_Facteurs).

backtrack([succes_global], _Branche, _QuantPred, _QuantSuiv, Stock, flot(Facteurs_In, Facteurs_Out)) :-
	!,
	insert_bl_from_stock(Stock,  Facteurs_In, Facteurs_Out).

backtrack([succes_global | Trace], Branche, QuantPred, [], Stock, flot(Facteurs_In, Facteurs_Out)) :-
	!,
	insert_bl_from_stock(Stock, Facteurs_In, Facteurs_),
	backtrack(Trace, Branche, QuantPred, [], [], flot(Facteurs_, Facteurs_Out)).

backtrack(Trace, [(X, _Val_X) | Branche], [Q | QuantPred], QuantSuiv, Stock, Flot_Facteurs) :-
	Trace = [branch(Z, _Val_Z) | _Trace_],
	(Q=e(Y,_);Q=a(Y,_)), X == Y,
	X == Z, !, % Le point de choix été retrouvé
	descente(Trace,  Branche, QuantPred, [Q | QuantSuiv],  Stock, Flot_Facteurs).

backtrack(Trace, [(X, _Val_X) | Branche], [Q | QuantPred], QuantSuiv, Stock, Flot_Facteurs) :-
	Trace = [branch(Z, _Val_Z) | _Trace_],
	(Q=e(Y,_);Q=a(Y,_)), X == Y,
	X \== Z,
	backtrack(Trace, Branche, QuantPred, [Q | QuantSuiv],  Stock, Flot_Facteurs).

% destocke_universelle/9
destocke_universelle(X, Branche, Coupe, QuantPred, QuantSuiv, QuantPred_Out, QuantSuiv_Out, Stock_In, Stock_Out) :-
	coupe(X, Branche, Coupe, QuantPred, QuantPred_Out, QuantSuiv, QuantSuiv_Out),
	map_supprime_avec_suffixe([(X, _) | Coupe], Stock_In, Stock_Out).

map_supprime_avec_suffixe(_Branche, [], []).
map_supprime_avec_suffixe(Coupe, [Branche | Stock_In], Stock_Out) :-
	map_supprime_avec_suffixe(Coupe, Stock_In, Stock_),
	(
	  \+(\+suffix(Coupe, Branche))
	->
	  Stock_Out = Stock_
	;
	  Stock_Out = [Branche | Stock_]
	).


coupe(X, [(Y, _Val_X) | Branche], Branche, [Q | QuantPred], QuantPred, QuantSuiv, [Q | QuantSuiv]) :-
	(Q=e(Z,_);Q=a(Z,_)), Z == X,
	X == Y, !.
coupe(X, [_ | Branche], Branche_, [Q | QuantPred], QuantPred_Out, QuantSuiv_In, QuantSuiv_Out) :-
	coupe(X, Branche, Branche_, QuantPred, QuantPred_Out, [Q | QuantSuiv_In], QuantSuiv_Out).


