90 likes | 218 Views
Úvod. Úkol: dosáhnout toho, aby se sekce jednoho kurzu nevyučovaly ve stejný čas. Toto omezení bylo uděláno stejně jako disjunce kurzů pro jednotlivé učitele viz. predikát instructor_constr( Lvcsid ) v modulu faculty.pl a příslušné predikáty v modulu routine.pl.
E N D
Úvod Úkol: dosáhnout toho, aby se sekce jednoho kurzu nevyučovaly ve stejný čas. Toto omezení bylo uděláno stejně jako disjunce kurzů pro jednotlivé učitele viz. predikát instructor_constr( Lvcsid ) v modulu faculty.pl a příslušné predikáty v modulu routine.pl Disjunkce sekcí jednotlivých kurzů
Postup řešení (1) Krok 1: Setřiď jednotlivé záznamy podle jejich identifikace a zpracuj je v Kroku 2 sections_constr( LVcsid0 ) :- ( disjunctive_sections( on ) -> quicksort( LVcsid0, LVcsid - [], csid ), mprint( format, [ '\nDisjunctive constraint over all \c sections for each course.\n\n'], summary1), bb_put( sum_of_cons, 0 ), go_through_course( LVcsid, [], _ ), bb_get( sum_of_cons, SumOfCon ), mprint( format, [ '\nNumber of disjunctions: ~d\n\n', [SumOfCon]], summary1) ; true ). go_through_course( [], LVcsidSame, Ccourse ) :- !, make_sections_disjunctive( LVcsidSame, Ccourse, [], [], [] ). go_through_course( [Vcsid|LVcsid], LVcsidSame, Ccourse ) :- Vcsid = csid( id( Ccourse, _, _ ), _, _, _, _, _ ), ( LVcsidSame = [] ; LVcsidSame = [ csid( id( Ccourse, _, _ ), _, _, _, _, _ ) | _ ] ), !, go_through_course( LVcsid, [Vcsid|LVcsidSame], Ccourse ). go_through_course( LVcsid, LVcsidSame, Ccourse ) :- make_sections_disjunctive( LVcsidSame, Ccourse, [], [], [] ), go_through_course( LVcsid, [], _ ). Krok 2: Vyber záznamy všech sekcí jednoho kurzu a zpracuj je v Kroku 3, to dělej dokud není seznam prázdný Disjunkce sekcí jednotlivých kurzů
Postup řešení (2) Krok 3: Vyber ze záznamů všechny proměnné pro čas a k ním odpovídající délky trvání a pokračuj krokem 4 make_sections_disjunctive( LVcsid, _, [], [], [] ) :- length( LVcsid, 1 ), !. make_sections_disjunctive( [], Cprint, LDtimes, LCdur, LCid ) :- !, disjunctive_per_day( LDtimes, LCdur, Cprint, LCid ). make_sections_disjunctive( [csid(Cid, base( CnbrMtgs, Cdur,_,_),_,_, LDtimes1, _ ) | LVcsid ], Cprint, LDtimes0, LCdur0, LCid0 ) :- append( LDtimes1, LDtimes0, LDtimes), dur_id_append( CnbrMtgs, Cdur, LCdur0, LCdur, Cid, LCid0, LCid ), make_sections_disjunctive( LVcsid, Cprint, LDtimes, LCdur, LCid ). dur_id_append( 1, Cdur, LCdur, [Cdur|LCdur], Cid, LCid, [Cid|LCid] ) :- !. dur_id_append( C0, Cdur, LCdur0, LCdur, Cid, LCid0, LCid ) :- C is C0 - 1, dur_id_append( C, Cdur, [Cdur|LCdur0], LCdur, Cid, [Cid|LCid0], LCid). Disjunkce sekcí jednotlivých kurzů
Postup řešení (3) disjunctive_per_day( Starts, Durations, Print, LCid ) :- max_slice( Slices ), fdset_interval( DaySet, 0, Slices ), mprint( disjunctive, [ Durations, DaySet, _, Print ], constraint ), mprint( print, ' ... summary\n', constraint ), days( Days ), disjunctive_per_day( Days, Starts, Durations, Print, LCid ), mprint( print, '\n', constraint ). disjunctive_per_day( 0, _, _, _, _ ) :- !. disjunctive_per_day( Days0, Starts, Durations, Print, LCid ) :- slices_day(Slices), Begin is Days0 * Slices - Slices, End is Days0 * Slices - 1, fdset_interval( DaySet, Begin, End ), disjunctive_one_day( Starts, Durations, Print, LCid, DaySet, [], [], []), Days is Days0 - 1, disjunctive_per_day( Days, Starts, Durations, Print, LCid ). Krok 4: Zjisti interval časových jednotek odpovídající jednomu dni a předej ho do kroku 5 společně s časovými proměnnými včetně jim odpovídajích délek trvání, to udělej pro všechny jednotlivé dny Disjunkce sekcí jednotlivých kurzů
Postup řešení (4) Krok 5: Vyber se seznamu proměnných (včetně jim odpovídajících délek trvání) ty, jejichž doména má průnik s intervalem pro právě zpracovávaný den, a pokud je to možné, tak na ně pošli omezení serialized disjunctive_one_day( [], [], _, [], _, [], [], [] ) :- !. disjunctive_one_day( [], [], Print, [], DaySet, Starts, Durations, Ids ) :- mprint( disjunctive, [ Durations, DaySet, _, Print ], constraint ), sum_list( Durations, SumLCdur ), slices_day( Slices ), ( SumLCdur =< Slices -> serialized( Starts, Durations ), bb_get( sum_of_cons, Sum ), NewSum is Sum + 1, bb_put( sum_of_cons, NewSum ) ; mprint( format, [ '\n !!! Do not possible make these sections: '], error ), remove_duplicates( Ids, PrintIds ), mprint( list, PrintIds, error ), mprint( format, [' disjunctive !!!' ], error ) ), mprint( print, ' ... OK\n', constraint ). disjunctive_one_day( [ Start | Starts ], [Duration | Durations], Print, [Id|LCid], DaySet, DayStarts0, DayDurations0, Ids0 ) :- fd_set( Start, StartSet), ( fdset_intersect( StartSet, DaySet) -> DayStarts = [ Start | DayStarts0 ], DayDurations = [ Duration | DayDurations0 ], Ids = [ Id | Ids0 ] ; DayStarts = DayStarts0, DayDurations = DayDurations0, Ids = Ids0 ), disjunctive_one_day( Starts, Durations, Print, LCid, DaySet, DayStarts, DayDurations, Ids ). Disjunkce sekcí jednotlivých kurzů
Ukázka výpisu Disjunctive constraint over all sections for each course. Disjunctive: aAae203_, 0..104: nbr 30-min mtgs: 12 ... summary Disjunctive: aAae203_, 84..104: nbr 30-min mtgs: 4 ... OK Disjunctive: aAae203_, 42..62: nbr 30-min mtgs: 4 ... OK Disjunctive: aAae203_, 0..20: nbr 30-min mtgs: 4 ... OK Disjunctive: aAd_255_, 0..104: nbr 30-min mtgs: 12 ... summary Disjunctive: aAd_255_, 63..83: nbr 30-min mtgs: 6 ... OK Disjunctive: aAd_255_, 21..41: nbr 30-min mtgs: 6 ... OK . . . Disjunctive: stat113_, 42..62: nbr 30-min mtgs: 8 ... OK Disjunctive: stat113_, 21..41: nbr 30-min mtgs: 4 ... OK Disjunctive: stat113_, 0..20: nbr 30-min mtgs: 4 ... OK Number of disjunctions: 451 Začátek Celkový počet omezení serialized, která byla vytvořena Disjunkce sekcí jednotlivých kurzů
Výsledky pro 3x50_2x75_1x50_2x50 V následující tabulce jsou uvedeny dosažené výsledky pro datovou sadu 3x50_2x75_1x50_2x50. V prvním sloupci jsou výsledky iniciálního řešení bez aktivního omezení pro disjunkci sekcí jednotlivých kurzů. Ve sloupci druhém již bylo při hledání iniciálního řešení omezení aktivováno - a bylo vytvořeno celkem 451 omezení typu serialized. Disjunkce sekcí jednotlivých kurzů
sort.pl V tomto modulu je implementována metoda (quicksort)pro třídění seznamu od nejmenšího po největší. Volá se pomocí predikátu quicksort( Input, Output-[], Method ), kde Method označuje klíč podle kterého se seznam bude třídit. V modulu je implementováno (pomocí predikátu less_eq( Key, X, Y) ) např. třídění seznamu identifikátorů kurzů (tedy jejich sekcí) podle jména instruktora (lexikograficky) apod. quicksort( LVcsid, LVcsid0-[], instr ) Disjunkce sekcí jednotlivých kurzů
print.pl V tomto modulu jsou implementovány obecné a speciální tiskové procedury ve tvaru mprint( How, What, Trace ). Tímto se říká, při jakém trasovacím módu se má tisknout - viz. parameters.pl (např. error). Označuje, jaká metoda (print, format) pro tisk se použije, nebo můžeme říci, že tiskneme list, apod. V tomto argumentu je to, co se má tisknout (řetězec, seznam, ...). Disjunkce sekcí jednotlivých kurzů