[1] Orar pe o școală fără profesori (IV)
[2] V.Bazon - De la seturi de date și limbajul R, la orare școlare (Google Books)
[3] V. Bazon - Orare școlare echilibrate și limbajul R (Google Books)
Tuplajul (9A 9C 9D)
/ (Fr2 Fr3 Gr1)
, cu două ore (una Lu
și cealaltă Mi
, v. [1]) este unul „cuminte”: putem asocia 9A
lui Fr2
, 9C
lui Fr3
și 9D
lui Gr1
, impunând apoi celor trei clase câte o aceeași zi, la cei trei profesori; într-o anumită oră a zilei, aceștia vor împărți cum știu ei, elevii claselor inițiale în trei grupe (pe care le renotăm "9A
", "9B
", "9C
") și va intra fiecare la grupa asociată lui.
… Cât pe ce să uităm: avem și un set separat "tuplaje.RDS
" (v. [1]-III) de 5 tuplaje „cuminți” (câte un simultan de doi profesori pe două clase), pentru "Des/Muz
".
În schimb, pentru tuplajele de două clase cu trei profesori, sau de trei clase cu patru profesori, nu mai putem asocia "one-to-one", câte o clasă la câte un profesor…
Putem proceda foarte simplu (câtă vreme ne găndim la repartizarea lecților pe zile, nu încă pe orele zilei): ignorăm (deocamdată) unul dintre profesorii „în plus”. Am ales să „ignorăm” Fr3
(care dintre cei angajați în tuplaje are cel mai puține ore proprii, în afara tuplajelor) și Fr1
; de exemplu, în tuplajul (10B 10C 10E)
/ (Fr1 Fr2 Fr3 Gr2)
eliminăm "Fr3
", iar în tuplajul inițial (11C 11E) /
ștergem "(Fr1 Fr2 Gr1
)Fr1
":
library(tidyverse) tpl <- readRDS("tuplaje_b.RDS") # v. [1] tpl <- edit(tpl) cls prof zl 1 09A 09C 09D Fr2 Fr3 Gr1 Lu 2 09A 09C 09D Fr2 Fr3 Gr1 Mi 3 09B 09E Fr1 Gr1 Ma # fără Fr3 4 09B 09E Fr1 Gr1 Vi 5 10A 10D Gr1 Gr2 Jo # fără Fr3 6 10A 10D Gr1 Gr2 Lu 7 10B 10C 10E Fr1 Fr2 Gr2 Mi # fără Fr3 8 10B 10C 10E Fr1 Fr2 Gr2 Ma 9 11A 11B 11D Fr2 Fr3 Gr1 Vi 10 11A 11B 11D Fr2 Fr3 Gr1 Jo 11 11C 11E Fr2 Gr1 Lu # fără Fr1 12 11C 11E Fr2 Gr1 Mi 13 12A 12B Gr1 Gr2 Ma # fără Fr1 14 12A 12B Gr1 Gr2 Vi 15 12C 12E Fr1 Gr2 Jo # fără Fr3 16 12C 12E Fr1 Gr2 Lu
și continuăm programul început mai sus, asociind pentru fiecare tuplaj, câte o clasă câte unui profesor, păstrând zilele alocate în [1] tuplajelor respective:
TP <- map_dfr(1:nrow(tpl), function(i) { vcl <- strsplit(tpl[i, 1], " ")[[1]] # clase vpr <- strsplit(tpl[i, 2], " ")[[1]] # profesori ("one-to-one") data.frame(prof = vpr, cls = vcl, zl = tpl[i, 3]) }) saveRDS(TP, "tuplaje_5.RDS") prof cls zl 1 Fr2 09A Lu # (9A 9C 9D) / (Fr2 Fr3 Gr1) Lu 2 Fr3 09C Lu 3 Gr1 09D Lu 4 Fr2 09A Mi # (9A 9C 9D) / (Fr2 Fr3 Gr1) Mi 5 Fr3 09C Mi 6 Gr1 09D Mi ...
Bineînțeles că atunci când va fi să vedem distribuțiile pe zile ale profesorilor, va trebui să contorizăm la Fr3
și la Fr1
clasele din tuplajele din care i-am exclus mai sus.
Avem (v. [1]) un cuplaj Ds1Mz1
(la clasa 12E
) și 4 cuplaje "Fr/Gr
" (la 11E
, 12D
și 12E
); constituim listele care asociază profesor sau cuplaj, cu cei (profesori sau cuplaje) de care depinde alocarea lecțiilor sale:
Tw1 <- list(Ds1 = "Ds1Mz1", Mz1 = "Ds1Mz1", Fr1 = c("Fr1Gr1", "Fr1Gr2"), Fr2 = "Fr2Gr1", Gr1 = c("Fr1Gr1", "Fr2Gr1"), Gr2 = "Fr1Gr2") Tw2 <- list(Ds1Mz1 = c("Ds1", "Mz1"), Fr1Gr1 = c("Fr1", "Gr1", "Fr1Gr2", "Fr2Gr1"), Fr1Gr2 = c("Fr1", "Gr2", "Fr1Gr1")) save(Tw1, Tw2, file="Tw12.Rda")
Listele Tw1
și Tw2
ne vor fi utile mai ales atunci când vom trece la repartizarea pe ore a lecțiilor dintr-o aceeași zi (o lecție în cuplaj nu poate cădea în aceeași oră cu o lecție a unuia dintre profesorii care formează cuplajul respectiv).
Procedând la fel ca în [4], obținem o repartizare pe zile R12
a tuturor celor 1026 lecții prof|cls
(am adăugat și cele 10 linii din "tuplaje.RDS
"):
> addmargins(table(R12[c('cls','zl')])) [35, ] Lu Ma Mi Jo Vi Sum 205 205 205 205 206 1026
R12
este echilibrată nu numai pe zile (cum se vede mai sus), dar și pe clase și pe profesori (cu diferență de cel mult 1 între numărul de ore/zi ale clasei, respectiv ale profesorului); de exemplu, distribuția pe profesori și pe zile a lecțiilor de "Română
":
Ro <- R12 %>% filter(grepl("Ro", prof)) sink("Ro.txt") print(tidy_as_csv(Ro), width=120, print.gap=2, row.names=FALSE, right=FALSE) sink() prof Lu Ma Mi Jo Vi Ro1 07A 07B 10D 07A 07B 10D 07A 07B 10D 11C 07A 07B 11C 07A 07B 10D 11C Ro2 09A 09B 12E 09B 11D 12E 09A 09B 11D 12E 09A 09B 12E 09A 11D 12E Ro3 06A 06C 08D 06C 08D 09C 06A 08D 09C 06A 06C 08D 09C 06A 06C 09C Ro4 05B 08A 10E 05B 06B 08A 10E 05B 06B 08A 10E 05B 06B 08A 05B 06B 10E Ro5 05C 09D 10C 05C 09D 11A 05C 09D 11A 05C 10C 11A 05C 09D 10C 11A Ro6 09E 12B 12C 09E 12A 12B 09E 12A 12B 12C 09E 12A 12C 09E 12A 12B Ro7 08C 10A 12D 08C 10A 11E 08C 11E 12D 08C 10A 11E 10A 11E 12D Ro8 08B 11B 08B 10B 10B 11B 08B 11B 08B 10B Ro9 05A 07C 07C 07D 05A 07C 07D 05A 07C 07D 05A 07D
Avem poate excepții (distribuții individuale neomogene), la profesori implicați în tuplajele Fr/Gr
:
prof Lu Ma Mi Jo Vi Fr1 05B 12C 11C 06C 09B 10B 12A 06C 10B 11C 08A 12C 05B 08A 09B 12A Fr1Gr1 12D 12D Fr1Gr2 12E Fr2 05C 09A 11C 10C 09A 10C 11C 07A 11A 05C 07A 11A Fr2Gr1 11E Fr3 07B 09C 10A 12C 08B 9B 10B 09C 10B 08B 11B 12C 10A 07B 11B 9B Gr1 06A 09D 10A 11E 06A 08C 09E 12A 07C 09D 11E 08C 10A 11D 07C 09E 11D 12A Gr2 05A 08D 10D 12E 07D 10E 12B 05A 10E 06B 07D 10D 12E 06B 08D 12B
Am evidențiat aici, prin boldare, cele două lecții (de Lu
și Mi
) ale tuplajului "cuminte" (09A 09C 09D)
/ (Fr2 Fr3 Gr1)
; se pot descoperi ușor și lecțiile celorlalte tuplaje.
Dar să ne amintim că din unele tuplaje scosesem fie Fr3
, fie Fr1
; mai sus (dar nu în R12
, fiindcă am mări artificial numărul de ore la clasele respective) am adăugat (cu blue) și lecțiile „omise”, la câte una dintre clasele tuplajelor respective. De exemplu, tuplajului (10A 10D)
/ (Fr3 Gr1 Gr2)
îi corespund mai sus (
din zilele 10A
10A 10D)Lu
și Jo
.
Fr1
de exemplu, are Lu
și Mi
câte 4 ore, dintre care una (la 12D
) în cuplaj cu Gr1
și una în tuplajul pe (11C 11E)
, împreună cu Fr2
și Gr1
; iar Ma
, are 5 ore dintre care una în cuplaj cu Gr2
(la 12E
) și una în tuplajul pe (12A 12B)
cu Gr1
și Gr2
.
Dacă vrem neapărat, putem omogeniza și distribuțiile celor implicați în tuplaje (v. [4]); de exemplu, Gr1
are distribuția (5 4 4 3 4)
și o putem omogeniza mutându-i o clasă neaflată în tuplaje (06A
) din ziua Lu
în ziua Jo
:
> recast_by_swap("Gr1") # v. [4]; vizează numai lecțiile proprii Gr1 [1,] 06A 09D 10A 11E # + 12D (cuplaj) [2,] 06A 08C 09E 12A [3,] 07C 09D 11E # + 12D (cuplaj) [4,] 08C 10A 11D [5,] 07C 09E 11D 12A Mutăm o clasă - din care Z1 în care Z2: 1 4 Interschimbăm cu unul dintre profesorii: 1: Is3 08B 11A 12E 08B 08C 11A 05A 08C 12E 05A 05C 06A 12E 05C 09B 12C # ... (încă 8 profesori cu care s-ar putea interschimba o clasă) Mutăm una dintre clasele 06A 09D 11E din Jo în Lu la al câtelea profesor (0 to Cancel): 1 Clasa de interschimbat între Gr1 și Is3: 06A
După interschimbarea Lu
↔ Jo
a clasei 06A
între Gr1
și Is3
, ambii profesori rămân cu distribuții orare omogene. Dar… am avut noroc: Is3
este singurul dintre cei 9 profesori, căruia interschimbarea respectivă nu-i „strică” distribuția orară; așa că nu am mai încercat omogenizarea și pentru ceilalți implicați în tuplaje.
Instrumentarea din [4] (preluată și aceasta, din [2] și [3]) pentru alocarea pe ore a tuplajelor, viza cazul particular (dar cel mai obișnuit) când în fiecare tuplaj sunt tot atâția profesori cât și clase. Putem încerca să reducem situația curentă (simultane de trei profesori pe două clase, etc.) la acest caz particular (cam cum am făcut mai sus, pentru repartizarea pe zile a tuplajelor)…
Reluăm tuplajele în forma inițială (v. [1]) și le separăm pe zile, adăugând un câmp "ora
" cu valoarea inițială 0
:
TJ <- readRDS("tuplaje_b.RDS") %>% mutate(ora = 0L) %>% split(.$zl) %>% lapply(., select, -zl) saveRDS(TJ, "tj2.RDS") > TJ[["Mi"]] # pentru ilustrare cls prof ora 2 09A 09C 09D Fr2 Fr3 Gr1 0 7 10B 10C 10E Fr1 Fr2 Fr3 Gr2 0 12 11C 11E Fr1 Fr2 Gr1 0
Să presupunem că pentru ziua Mi
ajungem să alocăm pe ore lecțiile clasei 10C
(pentru care se vede întâi, că face parte din tuplajul TJ[["Mi"]][2, ]
):
R12 %>% filter(cls=="10C", zl=="Mi") %>% select(prof) %>% mutate(ora = sample(nrow(.))) %>% as.data.frame() prof ora 1 SP2 5 2 In2 6 3 Sp1 2 4 Mt5 3 5 En5 1 6 Fr2 4
Dacă SP2
de exemplu, nu este liber în ora 5 (fiindcă la o clasă tratată anterior, i s-a alocat deja ora 5), atunci se va genera în coloana ora
o altă etichetare cu 1:6.
Să presupunem că alocarea redată mai sus este admisibilă pentru primele 5 linii și ajungem la Fr2
din linia 6; fiindcă Fr2
face parte din tuplajul identificat la început, se consultă valoarea din câmpul "ora
" a acestui tuplaj: dacă este 0
, atunci se înscrie în loc 4
și alocarea lecțiilor clasei 10C
este încheiată (și se va trece la alocarea lecțiilor unei alte clase); dacă este h
≠ 0
, înseamnă că anterior s-a întâlnit una dintre celelalte clase ale tuplajului și deja s-a alocat ora h
, pentru tuplajul respectiv — dacă h
este chiar 4
, atunci alocarea la clasa 10C
este iarăși, încheiată; altfel (h
≠ 4
), alocarea curentă trebuie respinsă (fiindcă profesorii din tuplaj trebuie să intre simultan, la clasele din tuplaj).
Raționamentul expus mai sus nu este tocmai corect, având în vedere numai tuplajele pe "Fr/Gr
"; se poate ca 10C
, sau 10E
să facă parte și din tuplaje pe alte discipline.
În "tj2.RDS
" avem pe zile, tuplajele pe "Fr/Gr
"; să formulăm și tuplajele pe "Des/Muz
":
TJ <- readRDS("tuplaje.RDS") %>% split(.$zl) %>% lapply(., function(J) data.frame(cls = paste(J$cls, collapse=" "), prof = paste(J$prof, collapse=" "), ora = 0L)) saveRDS(TJ, "tj1.RDS") > TJ[["Mi"]] # ilustrare cls prof ora 1 10E 11E Ds1 Mz1 0
Până la urmă… dacă este bună, încercarea schițată mai sus, de "reducere" prin eliminarea unuia, ar impune modificări importante în programul de repartizare pe ore ("mount_h1.R
" din [2]) pe care, ca și în [4], vrem să-l folosim aici; în principiu, lecțiile marcate cu blue mai sus (care au fost "reduse" lui Fr3
și Fr1
) trebuie totuși, materializate în orar și nu doar subânțelese…
vezi Cărţile mele (de programare)