q(Makespan):-     statistics(runtime,_),
%        asserta(nbmach(M)), asserta(nbjobs(N)),
        openshop(XIJ, Makespan), statistics(runtime,[_,Y]),
        write(XIJ), nl,
	write(Makespan), nl,
	write('Time : '), write(Y), write(' ms'), nl.

:- include('44data.pl').

openshop(X, Makespan) :-
	nbMachines(Machs),
	nbJobs(Jobs),
	make_vars(Machs, Jobs, X, Makespan),
	post_makespan_cstr(X, Makespan),
	post_machine_cstr(Machs, Jobs, X),
	post_job_cstr(Machs, Jobs, X),
        fd_minimize(fd_labeling(X), Makespan).

make_vars(Machs, Jobs, X, Makespan) :-
	MJ is Machs * Jobs,
	upper_bound(UB),
	length(X, MJ),
	fd_domain([Makespan|X], 0, UB).

post_makespan_cstr(X, Makespan) :-
	findall(Pjm, p(_,_,Pjm), P),
	set_makespan(X, P, Makespan).

set_makespan([], [], _).
set_makespan([Xjm|X], [Pjm|P], Makespan) :-
	Makespan #>=# Xjm + Pjm,
	set_makespan(X, P, Makespan).

post_machine_cstr(0, _, _).
post_machine_cstr(M, J, X) :-
	post_mach_job_cstr(M, J, X),
	M1 is M - 1,
	post_machine_cstr(M1, J, X).

post_mach_job_cstr(_, 0, _).
post_mach_job_cstr(M, J, X) :-
	J1 is J - 1,
	post_mach_job_task_cstr(M, J, J1, X),
	post_mach_job_cstr(M, J1, X).

post_mach_job_task_cstr(_, _, 0, _).
post_mach_job_task_cstr(M, J, J1, X) :-
	nbMachines(Machs),
	A is (J  - 1) * Machs + M,
	B is (J1 - 1) * Machs + M,
	nth(A, X, Xjm),
	nth(B, X, Xj1m),
	p(J,  M, Pjm),
	p(J1, M, Pj1m),
	(
	    Xjm + Pjm #=<# Xj1m ;
	    Xj1m + Pj1m #=<# Xjm
	),
	J2 is J1 - 1,
	post_mach_job_task_cstr(M, J, J2, X).

post_job_cstr(_, 0, _).
post_job_cstr(M, J, X) :-
	post_job_mach_cstr(M, J, X),
	J1 is J - 1,
	post_job_cstr(M, J1, X).

post_job_mach_cstr(0, _, _).
post_job_mach_cstr(M, J, X) :-
	M1 is M - 1,
	post_job_mach_task_cstr(M, J, M1, X),
	post_job_mach_cstr(M1, J, X).

post_job_mach_task_cstr(_, _, 0, _).
post_job_mach_task_cstr(M, J, M1, X) :-
	nbMachines(Machs),
	A is (J - 1) * Machs + M,
	B is (J - 1) * Machs + M1,
	nth(A, X, Xjm),
	nth(B, X, Xjm1),
	p(J, M,  Pjm),
	p(J, M1, Pjm1),
	(
	    Xjm + Pjm #=<# Xjm1 ;
	    Xjm1 + Pjm1 #=<# Xjm
	),
	M2 is M1 - 1,
	post_job_mach_task_cstr(M, J, M2, X).
