01 Mit csinál a rendszer
Egy szöveges tantárgyfelosztásból automatikusan előállít egy teljes, ütközésmentes heti órarendet, és megjeleníti böngészőben.
A bemenet egy Python-fájl, amelyben felsorolod, hogy melyik tanár melyik osztálynak hány órát tanít, milyen teremben, és milyen megkötésekkel. A program ebből kiszámol egy olyan órarendet, amelyben egyszerre teljesül minden kötelező szabály:
- egy tanár egyszerre csak egy helyen tanít,
- egy osztálynak egyszerre csak egy órája van,
- egy teremben egyszerre csak egy óra folyik,
- minden tantárgyból pontosan annyi óra van, amennyi elő van írva,
- az osztályok napja az 1. órán kezdődik és nincs benne lyukasóra.
A kimenet egyetlen orarend.html fájl, amit bármelyik böngésző megnyit —
internet és telepített program nélkül is. Ebben osztály, tanár és terem szerinti
nézetek, szabad termek kimutatás, statisztika és PDF-export található.
Ez nem „próbálgatós" program. A megoldó matematikailag bizonyítja, hogy a talált órarend minden kötelező szabálynak megfelel — vagy megmondja, hogy a megadott szabályok együtt teljesíthetetlenek. Nem fordulhat elő rejtett ütközés.
02 A modell: CP-SAT
Korlátozás-programozás (constraint programming), nem táblázatkezelés és nem mesterséges intelligencia.
A rendszer a Google OR-Tools csomag CP-SAT nevű megoldóját használja. A CP-SAT egy úgynevezett constraint solver: megadsz neki ismeretlen döntéseket és a rájuk vonatkozó szabályokat, ő pedig megkeresi azt a beállítást, amely minden szabálynak megfelel.
Hogyan lesz az órarendből matematika
Minden lehetséges „óra elhelyezés" egy igen/nem döntés. Például:
| Változó | Jelentése | Értéke |
|---|---|---|
x[Töri Teri, 7.a, kedd, 3. óra, TORI terem] |
Töri Teri kedden 3. órában történelmet tart a 7.a-nak a történelem teremben | 1 vagy 0 |
x[Matek Máté, 8.b, péntek, 6. óra, MAT terem] |
Matek Máté pénteken 6. órában matematikát tart a 8.b-nek | 1 vagy 0 |
Egy közepes iskolánál ez nagyjából 10–15 ezer ilyen döntés. A szabályok ezekre vonatkozó egyenlőtlenségek. Néhány példa, ahogy a program megfogalmazza őket:
| Szabály emberi nyelven | Ahogy a modell látja |
|---|---|
| Töri Teri kedden 3. órában legfeljebb egy helyen lehet | a rá vonatkozó összes ilyen időpontú változó összege ≤ 1 |
| A 7.a-nak pontosan 2 történelemórája van | a 7.a történelem-változóinak összege = 2 |
| A 6.b-nek nincs lyukasórája | ha a 4. órája foglalt, akkor a 3. is foglalt (foglaltság csökkenő sorozat) |
| A képzőművészet duplaóra | egyetlen döntés két egymás utáni órát foglal le egyszerre |
Miért ez a megközelítés
- Bizonyított helyesség. Ha megoldást ad, az minden kötelező szabálynak megfelel. Ha nincs megoldás, azt is megmondja — nem hallgat el ütközést.
- Optimalizál is. A kötelező szabályokon túl a „lehetőleg" típusú kívánságokat (lyukasórák száma, osztályfőnöki a nap végén) pontozza, és a legjobb összpontszámú órarendet keresi.
- Ingyenes és nyílt forráskódú. Nincs licencdíj, nincs felhő, nincs adatküldés — minden a saját gépen fut.
A CP-SAT nem „gondolkodik" és nem generál szöveget. Determinisztikus matematikai megoldó: ugyanaz a bemenet ugyanazt az eredményt adja. A tantárgyfelosztás megfogalmazása a Python-fájlban emberi munka — utána a számítás gépi.
03 Telepítés üres gépre
Windows gépen, ahol semmi nincs telepítve. Kb. 10 perc, internetkapcsolat szükséges (csak a telepítéshez).
-
Python telepítése
Töltsd le a legfrissebb Python 3 telepítőt a hivatalos oldalról:
https://www.python.org/downloads/
A legfontosabb lépésA telepítő első képernyőjén pipáld be az „Add python.exe to PATH" jelölőnégyzetet, és csak utána kattints az Install Now gombra. Enélkül a későbbi parancsok nem fognak működni, és újra kell telepíteni.
Ellenőrzés: nyiss egy parancssort (Windows gomb → írd be:
cmd→ Enter), és gépeld be:python --versionHa kiírja a verziót (pl.
Python 3.13.1), kész vagy. -
Az OR-Tools csomag telepítése
Ugyanabban a parancssorban:
pip install ortoolsEz letölti a megoldómotort (kb. 100 MB). Egyszer kell megcsinálni. Hivatalos oldal: developers.google.com/optimization
Ellenőrzés:
python -c "from ortools.sat.python import cp_model; print('OK')"Ha kiírja, hogy
OK, a motor működik. -
Böngésző
Az elkészült órarend megnyitásához és a PDF-exporthoz. A Windowsban lévő Edge is megfelel, de a Chrome és a Firefox is jó. Más nem kell — az órarend nem igényel internetet.
-
Szövegszerkesztő ajánlott
A Python-fájl szerkesztéséhez. A Jegyzettömb is működik, de kényelmesebb:
- Notepad++ — egyszerű, gyors
- Visual Studio Code — több segítség, hibajelzés
Word nem jóA Python-fájlt soha ne szerkeszd Wordben vagy más szövegszerkesztőben — az elrontja a formázást (idézőjelek, behúzás), és a program nem fog elindulni.
Ha nincs internet a célgépen
Egy internetes gépen töltsd le a csomagot, másold át pendrive-on, majd a célgépen:
04 A mappa tartalma
Minden fájl ugyanabba a mappába kerül. Ez a mappa bárhol lehet (asztal, dokumentumok) — csak együtt maradjanak.
| Fájl | Mi ez | Szerkeszted? |
|---|---|---|
orarend_cpsat.py |
A modell: az iskola adatai és a szabályok. Ez a lényeg. | igen |
futtat.bat |
Indító. Dupla kattintás — ellenőrzi a Pythont, telepíti az OR-Tools-t ha kell, majd lefuttatja a modellt. | nem |
orarend.html |
Az eredmény. A futtatás hozza létre (felülírja az előzőt). | nem |
orarend_forditas.py |
Opcionális: a kész órarendet átírja másik nyelvre. | ha kell |
futtat_forditas.bat |
Indító a fordításhoz. | nem |
Mielőtt nagyobb átalakításba kezdesz, másold le az orarend_cpsat.py
fájlt (pl. orarend_cpsat_mentes.py néven). Ha valami elromlik,
van hova visszatérni.
05 A Python-fájl felépítése
A fájl számozott blokkokból áll. Neked jellemzően csak az 1–8. blokkot kell átírni; a 9–12. blokk az általános logika, ami minden iskolánál ugyanaz.
| Blokk | Tartalma | Átírandó |
|---|---|---|
1. Alapadatok | napok, órák száma, osztályok, tantermek | igen |
1b. Tanári alapszabályok | max lyukasóra, max 7. óra, kivételek | igen |
1c. Szabadnapok | ki melyik napon nem tanít | igen |
1d. Napi minimum | kinek elég 1 óra egy adott napon | igen |
3. Tantárgyfelosztás | ki – mit – kinek – hány órában – hol | igen |
4. Testnevelés | összevont csoportok (fiú/lány) | igen |
5. Csoportbontás | technika / informatika váltás | igen |
6. Osztályfőnöki | ki melyik osztály főnöke | igen |
7. Hittan | kötött órák | ha van |
8. Napi sávok | egyedi kérések (ki mikor tanít) | ha kell |
9–10. Szabályok, célfüggvény | ütközés, folytonosság, pontozás | nem |
11–12. Megoldás, HTML | futtatás és megjelenítés | nem |
06 Saját adatok megadása
Az alábbi példákban minden név kitalált sablonnév — cseréld le a saját iskolád adataira.
Osztályok és tantermek
Az osztályokat rövid kóddal adjuk meg (a pont nélkül), a termeket szintén:
# Osztalyok: az "5a" a megjelenitesben "5.a" lesz
CLASSES = ["5a", "5b", "6a", "6b",
"7a", "7b", "8a", "8b"]
# Tantermek: rovid kod -> megjeleno nev
ROOMS = {
"MAGY": "Magyar terem",
"MAT": "Matematika terem",
"TORI": "Történelem terem",
"LAB": "Kémia/Fizika labor",
"INF": "Informatika terem",
"TORNA":"Tornaterem",
}
Tantárgyfelosztás — a leggyakoribb sor
Minden tanár minden osztályához egy sor. A jelentése: ki, melyik osztálynak, mit, hány órában, melyik teremben.
# Tortenelem - Tori Teri, a tortenelem teremben
for k, h in [("5a", 2), ("5b", 2), ("6a", 2), ("6b", 2)]:
add_course("Töri Teri", k, "Történelem", h, "TORI")
# Matematika - Matek Mate, heti 4 ora, de 7. oran nem lehet
for k in ["7a", "7b", "8a", "8b"]:
add_course("Matek Máté", k, "Matematika", 4, "MAT",
periods=NO_SEVENTH)
# Angol - Angol Anna, csak hetfon, szerdan es penteken tanit
for k in ["5a", "5b", "6a"]:
add_course("Angol Anna", k, "Angol", 3, "NYELV",
days={PON, SRE, PET})
| Beállítás | Mit jelent | Példa |
|---|---|---|
days= | mely napokon tarthatja | days={PON, SRE, PET} |
periods= | hányadik órákban | periods={1,2,3} |
NO_FIRST | ne legyen 1. órája | periods=NO_FIRST |
NO_SEVENTH | ne legyen 7. órája | periods=NO_SEVENTH |
| több terem | a megoldó választ közülük | ["MAGY","TORI","KONYV"] |
A napok rövidítése: PON hétfő, UTO kedd,
SRE szerda, CET csütörtök, PET péntek.
Duplaóra
Ha egy tantárgy két órája egymás után kell, hogy menjen:
# Rajz Rozsa: az 5. evfolyamon duplaora, a rajzteremben
for k in ["5a", "5b"]:
add_double_course("Rajz Rózsa", k, "Rajz", "RAJZ",
{PON, SRE, PET}, # mely napokon
[(1,2),(2,3),(3,4),(4,5),(5,6),(6,7)])
Összevont testnevelés
Ha két osztály együtt tornázik (fiúk–lányok bontásban, két tanárral):
PE_TEACHERS = ["Torna Tamás", "Torna Tibor"]
# (osztalypar, heti oraszam) - a ket tanar egyszerre tartja
PE_COMBINED = [(("5a", "5b"), 3),
(("6a", "6b"), 3),
(("7a", "7b"), 3)]
# Egy tanar egyedul tartja (nincs osszevonas)
PE_SOLO = [("8a", 2), ("8b", 2)]
Csoportbontás (technika / informatika)
Ha egy osztály két csoportra oszlik és a két tantárgy párhuzamosan megy:
# Ezek az osztalyok csoportra bomlanak (A csoport info, B csoport technika)
BIG_TI = ["5a", "5b"]
# Ezeknel nincs bontas: kulon technika-duplaora + kulon 1 informatika ora
SMALL_TI = ["6a", "6b", "7a", "7b", "8a", "8b"]
TECH_TEACHER = {"5a": "Techi Tibor", "5b": "Techi Tibor"}
Ha egy osztály nincs csoportbontásban, a technika és az informatika két
külön óra — nem eshetnek egy időpontra. Ezt a rendszer automatikusan
kezeli, de csak akkor, ha az osztályt a SMALL_TI listába teszed.
Osztályfőnöki órák
# osztaly: (osztalyfonok, mely termekben lehet)
OF = {
"5a": ("Töri Teri", ["TORI"]),
"5b": ("Matek Máté", ["MAT"]),
"6a": ("Bio Bence", ["BIO", "KONYV"]), # tobb lehetoseg
}
# Kotott idopontok: osztaly -> (nap, ora)
OF_FIXED = {"5a": (PON, 7)} # 5.a: hetfo 7. ora
Ha egy osztályfőnöki óra sehogy sem fér be, be lehet tenni 0. órára (a tanítás előtti sávba) — a program erre külön lehetőséget ad.
Tanári alapszabályok és kivételek
# Alapszabaly: mindenkinek max 1 lyukasoraja (szuloi fogadoora)
# es max 1 hetedik oraja lehet. Az alabbi szotarakban adhatok a kivetelek.
SEVENTH_CAP_OVERRIDE = {
"Torna Tamás": 2, # neki 2 hetedik ora is lehet
"Rajz Rózsa": 2,
"Info Ivett": 0, # neki egyaltalan nincs 7. oraja
}
# Ki melyik napon NEM tanit (a tobbi napon kotelezoen igen)
DAY_OFF = {
"Német Nóra": {UTO, CET}, # kedden es csutortokon nincs
"Hittan Hanna": {PON, UTO, CET, PET}, # csak szerdan
}
# Kivetel a "naponta legalabb 2 ora" szabaly alol
ONE_LESSON_DAY_OK = {
"Német Nóra": {PET}, # penteken 1 ora is eleg
}
Egyedi kérések
A 8. blokkban lehet egyedi megkötéseket megfogalmazni. Néhány minta:
# Fizika Feri penteken csak az elso harom oraban tanit
for e in out:
if e["teacher"] == "Fizika Feri" and e["d"] == PET and e["p"] > 3:
m.Add(e["v"] == 0)
# Zene Zoli hetfon a nap vegen tanit (4-7. ora)
for e in out:
if e["teacher"] == "Zene Zoli" and e["d"] == PON and e["p"] < 4:
m.Add(e["v"] == 0)
07 Feltételtípusok
Háromféleképpen lehet szabályt megfogalmazni. A választás dönti el, mi történik, ha a szabály nem tartható.
kemény
Kötelező
A megoldó soha nem sértheti meg. Ha egy kemény szabály teljesíthetetlen, a program „nincs megoldás" üzenettel áll le.
Mire jó: ütközések, óraszámok, kötött időpontok.
lágy
Kívánság
Pontlevonás jár a megsértéséért. A megoldó igyekszik betartani, de ha muszáj, feláldozza egy fontosabb szabályért.
Mire jó: „lehetőleg a nap végén", „inkább ebben a teremben".
majdnem kemény
Kiemelt súly
Nagyon nagy pontlevonás. Gyakorlatilag kötelező, de nem tud megoldhatatlanná tenni — mindig kapsz órarendet.
Mire jó: fontos, de kockázatos szabályok.
A harmadik forma a legbiztonságosabb ott, ahol nem vagy biztos benne, hogy a szabály egyáltalán teljesíthető. A program a futás végén kiírja, mely tanároknál nem sikerült betartani — így pontosan látod, hol kell engedni.
Kezdd kevés kemény szabállyal. Futtasd le, nézd meg az eredményt, és utána szigoríts fokozatosan. Így mindig tudod, melyik újonnan bevitt szabály okozta a gondot — ha egyszerre teszel be tízet, nehéz megtalálni a ludast.
08 Futtatás
Dupla kattintás a futtat.bat fájlra.
A parancssori ablak megnyílik, és lépésenként kiírja, mi történik:
================================================
Iskolai orarend generalasa (CP-SAT / OR-Tools)
================================================
Hasznalt Python parancs: py
Python 3.13.1
Orarend szamitasa... (ez akar 1-2 percig is eltarthat)
Megoldo statusz: OPTIMAL
Celfuggveny-ertek (buntetes): 148
=== SZABALY-ELLENORZES (max 1 lyukasora / max 1 hetedik ora) ===
Lyukasora: MINDENKI betartja a szabalyt. :)
7. ora: MINDENKI betartja a szabalyt. :)
--- ONELLENORZES ---
OK: nincs tagozati lyukasora.
Kesz: orarend.html
| Üzenet | Jelentése |
|---|---|
OPTIMAL | Megvan a legjobb megoldás. Ennél jobb nincs. |
FEASIBLE | Érvényes órarend, de az idő lejárt a bizonyítás előtt. Használható; több idővel esetleg szebb lesz. |
INFEASIBLE | A megadott kötelező szabályok együtt teljesíthetetlenek. Lásd a következő szakaszt. |
A futásidő az iskola méretétől és a szabályok szigorúságától függ: néhány másodperctől néhány percig. A felső korlát a fájlban állítható:
solver.parameters.max_time_in_seconds = 900 # 15 perc
Amikor kész, nyisd meg az orarend.html fájlt dupla kattintással.
09 Ha nincs megoldás
Az INFEASIBLE nem hiba a programban — azt jelenti, hogy
az általad megadott kötelező szabályok egymásnak ellentmondanak.
A leggyakoribb okok
| Ok | Példa | Megoldás |
|---|---|---|
| Túl kevés hely a teremben | Két tanár 40 órányi tantárgyat tanít egyetlen teremben, de a héten csak 35 óra fér bele | Engedj meg tartalék termeket, vagy csökkentsd az óraszámot |
| Túl szűk napi sáv | Egy tanárnak 22 órája van, de csak 20 időpontot engedélyeztél neki | Számold össze: hány óra × hány engedélyezett időpont |
| Ütköző kötött órák | Két különböző óra ugyanarra a fix időpontra van rögzítve | Nézd át a kötött időpontokat |
| Az osztálynak nincs elég helye | Az osztálynak 38 órája van, de csak 35 időpont van a héten | Csökkentsd az óraszámot vagy engedélyezz 0./8. órát |
Hogyan találd meg a hibát
- Nézd meg, mit írt ki a program — a hibaüzenet felsorolja, mely beállításokat érdemes lazítani.
- Vedd ki az utoljára bevitt szabályt, és futtasd újra. Ha most megy, megvan a ludas.
- Ha nem tudod, melyik a hibás: kapcsold ki egyszerre az összes egyedi megkötést (a 8. blokkot), és tedd vissza őket egyesével.
- Számolj utána papíron: az adott tanár összes órája ≤ az engedélyezett időpontjai száma? Ez a leggyakoribb elszámolás.
Ha egy szabálynál nem vagy biztos, hogy teljesíthető, tedd „majdnem kemény" formába (kiemelt súllyal a lágy szabályok közé). Akkor mindig kapsz órarendet, és a program megmondja, hol nem sikerült betartani.
10 Fordítás másik nyelvre
Kétnyelvű iskolákban a kész órarend átírható másik nyelvre — az órarend érintetlenül marad, csak a megjelenő szövegek cserélődnek.
A fordítóscript elején szótárak vannak a tanárnevekhez, tantárgyakhoz és termekhez. Ezeket futtatás előtt átnézed, és ahol kell, javítod:
TANAROK = {
"Töri Teri": "Teri Tori",
"Matek Máté": "Mate Matek",
}
TANTARGYAK = {
"Történelem": "Istorija",
"Matematika": "Matematika",
}
TANTERMEK = {
"Történelem terem": "Kabinet istorije",
}
Futtatás után egy külön fájl keletkezik (pl. orarend_sr.html),
az eredeti pedig megmarad. A script a végén kiírja, ha valamelyik névhez nem
talált fordítást.
11 Linkek
Hivatalos források, ha mélyebbre szeretnél ásni.
| Mi | Cím |
|---|---|
| Python letöltés | python.org/downloads |
| Google OR-Tools | developers.google.com/optimization |
| CP-SAT dokumentáció | CP-SAT megoldó bemutatása |
| OR-Tools forráskód | github.com/google/or-tools |
| Notepad++ | notepad-plus-plus.org |
| Visual Studio Code | code.visualstudio.com |