Din [1] avem fişierul chosen_distr.rds
, conţinând o distribuţie pe zilele de lucru a orelor dintr-o şcoală cu un singur schimb – mai precis, un obiect "tibble" (putem să-i zicem şi „tabel”) cu 1202 înregistrări pe trei variabile, reprezentând câte un profesor (dintre cei 76 existenţi), o clasă (dintre cele 41 – nu 32, cum notasem greşit în [1]) şi ziua alocată orei la acea clasă pentru profesorul respectiv. Această distribuţie a fost aleasă ca fiind cea mai „promiţătoare”, dintr-o listă de vreo 30 de distribuţii generate în [1].
Vrem să îndreptăm cumva, distribuţiile individuale rezultate profesorilor cu mai puţin de 15 ore pe săptămână – fiindcă pentru aceştia nu am impus nicio condiţie la generarea distribuţiei (v. "distribute.R
" din [1]); dar vom considera şi cele câteva cazuri cu „coeficientul de omogenitate” peste 0.5, existente între distribuţiile individuale cu un total de cel puţin 15 ore – mărind astfel posibilităţile de schimbare dintr-o zi în alta a orelor la anumite clase (cu şansa de a îmbunătăţi şi aceste cazuri).
Prin programul următor separăm înregistrările corespunzătoare celor două categorii de cazuri menţionate mai sus. Întâi, recuperăm în D
distribuţia dată şi constituim (similar matricei Zore
din [1]) matricea Z
conţinând distribuţiile individuale, împreună cu totalurile şi coeficienţii de omogenitate aferenţi; integrăm (transformând matricea în "data.frame") şi coloana numelor profesorilor de care ţin distribuţiile individuale respective. Apoi, folosim Z
pentru a obţine prin funcţia sgr_dis()
, lista înregistrărilor din D
corespunzătoare uneia sau alteia dintre cele două categorii; prin funcţia make_df_sgr()
vom putea obţine şi o formă lizibilă, a datelor respective:
# subdis.R (separă subgrupul orelor de redistribuit pe zile) library(tidyverse) D <- readRDS("chosen_distr.rds") # 1202 ore (prof/cls) distribuite pe zile cf_omg <- function(ore_zi) { # coeficient de omogenitate (v. [1]) ore <- ore_zi[ore_zi != 0] round(sd(ore)/mean(ore)*diff(range(ore)), 2) } Z <- as.matrix(table(D[c("prof", "zl")])) %>% cbind(., apply(., 1, cf_omg)) %>% # coloana primeşte numele "V6" cbind(., rowSums(.[, 1:5])) # coloana primeşte numele "V7" Z[, c(6, 7)] <- Z[, c(7, 6)] # schimbă între ele ultimele două coloane nume <- rownames(Z) # profesorii de care aparţin distribuţiile din Z Z <- as.data.frame(Z) %>% mutate(prof = nume) %>% # adaugă coloana profesorilor relocate(., prof, before=1) Z1 <- Z %>% filter(V6 < 15) # subgrupul distribuţiilor cu sub 15 ore pe săptămână # > print(Z1) ## distribuţiile 2, 3, 16 şi 20 sunt bune, încât ignorăm liniile: Z1 <- Z1[-c(2,3,16,20), ] # (3 3 3 3 0), (2 2 0 0 0), (2 3 3 2 2) şi (0 0 2 2 2) Z2 <- Z %>% filter(V6 >= 15 & V7 > 0.5) # şi acestea ar fi eventual, de îndreptat sgr_dis <- function(sZ) { # produce lista înregistrărilor din D pentru Z1 sau Z2 D %>% filter(prof %in% sZ$prof) %>% split(.$zl) %>% map(., function(Z) Z[, 1:2] %>% arrange(prof)) } make_df_sgr <- function(sZ) { # pentru tipărit/afişat listele date de sgr_dis() hZ <- sgr_dis(sZ) patt <- data.frame(prof="", Lu="", Ma="", Mi="", Jo="", Vi="") r = 1 for(P in sZ$prof) { patt[r, 1] <- P for(q in 2:6) { ql <- hZ[[q-1]] %>% filter(prof == P) patt[r, q] <- paste(c(ql$cls), collapse=" ") } r <- r + 1 } patt } reD <- D %>% # comasează cele două liste (subgrupul orelor de re-distribuit pe zile) filter(prof %in% c(Z1$prof, Z2$prof)) saveRDS(reD, file="ore_de_redist.rds")
Bineînţeles că în final, am salvat (într-un fişier ".rds
") grupul de înregistrări din distribuţia iniţială D
, corespunzător distribuţiilor individuale din Z1
şi Z2
(urmând să re-distribuim orele din acest grup, iar după modificare, să le montăm înapoi în D
).
Acum, prin următoarea secvenţă de comenzi sintetizăm orele respective într-o formă pe care putem încerca chiar şi manual, să le redistribuim pe zile:
> df1 <- make_df_sgr(Z1) > df2 <- make_df_sgr(Z2) > df12 <- rbind(df1, df2) > sink("sgred.txt"); print(df12, row.names=FALSE, width=100); sink()
# distribuţia iniţială a orelor de re-distribuit pe zile prof Lu Ma Mi Jo Vi P56 6D 8D 10B 5B 6D 8D 10B 12B 5B 5C 6D 12B 5C P59 6D 7D 8B 5E 7D 8B 5E 5D 5E 6D 7D P60 11C 12D 12E 9E 12D 12E 11C 11C 12D 12E 9E P61 10C 5C 7A 7E 5B 5E 7C 5D 7D 5A P62 9C 10C 10D 12E 9C 10A 10B 9D 10E 9D P63 12A 12A 12C 11A 12C 9A 11A 11B 9A 11B P64 11D 11D 11D 11E 9C 9D 11E 9C 9D 11E P65 6E 9A 5A 8C 5B 7D 7E 6C 8E P66 5A 5B 9E 9D 9E 11E 9D 9D P67 7E 7E 8C 7E 8C 7E 8C P68 5C 12B 5C 12B 8C 5C 8C P69 9B 9D 11C 5C 9C 5C 11A P70 11A 9D 12A 11B 12B 9A P72 10A 10C 10D 11E 10B 10E P73 11E 12C 12E 9E 12E 9E P74 10E 10C 10D 10E P76 7B 7B P39 11A 12D 8C 8F 7E 8C 8D 8F 12E 7D 8D 8E 12E 7C 8E 11A 12A P40 11B 11D 8F 9A 11C 11D 8A 9A 8A 8B 11D 8B 9C 10E 11D 8F 9C P41 11E 12A 12D 7E 12D 7E 8D 12D 7A 8D 8E 12D 7A 8E 9E 11A 12C P42 10B 7B 9B 9E 5B 7B 9B 9E 10B 5B 9B 9E 10B 9B 10B 7B 9E P47 11A 7E 8A 9B 11A 12C 8A 8E 12C 8E 7E 8A 8E 7E 8A 9B P48 6E 8C 8D 9E 6C 6D 8B 9B 6A 8A 10B 6B 7B 8F 7B 8E P54 12E 6E 8F 12B 6E 12B 8F 12B 12E 6E 8F 12B 12E 6E 8F ## 5C se poate muta între P56 şi P61 ## 7E are 4, 3, 1, 3, 1 ore pe zi
Dăm un exemplu de re-distribuire manuală (folosind un editor de text, pentru a evidenţia sintactic apariţiile în text a uneia sau alteia dintre clase). P56
are distribuţia (2 4 5 2 0), de coeficient 1.38; evidenţiind în tot textul "5C", observăm că 5C
apare miercuri la P56
şi apare luni (dar nu şi miercuri) la P61
; mutând 5C
din ziua Mi
în ziua Lu
la P56
şi din ziua Lu
în ziua Mi
la P61
– ambele distribuţii se îmbunătăţesc (a lui P56
devine (3 4 4 2 0), cu omogenitatea 0.59; cea a lui P61
devine (3 3 2 1 1), ceva mai bună ca aceea iniţială).
Cu alte cuvinte, în distribuţia iniţială D
aveam înregistrările "P56 5C Mi
" şi "P61 5C Lu
" – iar după modificarea arătată, am avea "P56 5C Lu
" şi respectiv "P61 5C Mi
".
Mecanismul exemplificat se poate aplica manual relativ uşor, putând conduce la îmbunătăţirea distribuţiilor individuale respective (fără a afecta numărul de ore pe zi la clase) – dar pare dificil de automatizat printr-un program… În schimb, nu este prea greu de realizat un "widget jQuery" (analog celui din Ajustarea orarului) prin care să putem sesiza mai uşor ce interschimbări de ore ar fi mai bine de făcut şi totodată, să le putem face interactiv (cu posibilităţi de revenire), mai în siguranţă şi mai comod decât dacă am proceda manual (şi utilizabil pe orice subset de ore).
Pe de altă parte, cel mai bine ar fi (în loc să mutăm ore dintr-o zi în alta) să adaptăm cumva programul de generare distribute.R
din [1], încât să-l putem folosi şi pe un subset al încadrării pe clase iniţiale. De exemplu, vedem în tabelul redat mai sus că unele clase apar în fiecare zi (5C
, 7D
, 10B
, 11A
şi altele); deci orele corespunzătoare acestora vor putea fi etichetate prin orice permutare de Zile
(satisfăcând anumite condiţii) – încât se întrevede posibilitatea de a folosi iarăşi algoritmul de etichetare din distribute.R
; dificultatea ar consta în faptul că unele clase apar numai în unele zile (de exemplu, 8D
apare numai în trei coloane), deci orele aferente acestora trebuie etichetate cu un anumit subset din Zile
(pentru a nu afecta numărul de ore pe zi la clase).
O altă dificultate vine din faptul că acum, clasele implicate au un număr prestabilit de ore pe zi; de exemplu, clasa 7E
apare în tabelul de mai sus de 4 ori în prima coloană şi de 3, 1, 3, 1 ori respectiv, în celelalte zile – ori prin etichetarea din [1] orele clasei ar fi repartizate omogen (de exemplu, (2 3 3 2 2)).
vezi Cărţile mele (de programare)