Telepítés & adaptáció · nulláról

Órarendkészítő kézikönyv

Hogyan készíts automatikus, ütközésmentes iskolai órarendet egy üres számítógépen — a telepítéstől a kész, böngészőben megnyitható órarendig.

Motor: Google OR-Tools CP-SAT
Nyelv: Python 3
Kimenet: egyetlen HTML fájl

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ó.

Fontos különbség

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 nyelvenAhogy 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.
Nem nyelvi modell

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).

  1. 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és

    A 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 --version

    Ha kiírja a verziót (pl. Python 3.13.1), kész vagy.

  2. Az OR-Tools csomag telepítése

    Ugyanabban a parancssorban:

    pip install ortools

    Ez 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.

  3. 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.

  4. Szövegszerkesztő ajánlott

    A Python-fájl szerkesztéséhez. A Jegyzettömb is működik, de kényelmesebb:

    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:

pip download ortools -d ortools_csomag
pip install --no-index --find-links=ortools_csomag ortools

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ájlMi ezSzerkeszted?
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
Mentés

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.

BlokkTartalmaÁtírandó
1. Alapadatoknapok, órák száma, osztályok, tantermekigen
1b. Tanári alapszabályokmax lyukasóra, max 7. óra, kivételekigen
1c. Szabadnapokki melyik napon nem tanítigen
1d. Napi minimumkinek elég 1 óra egy adott naponigen
3. Tantárgyfelosztáski – mit – kinek – hány órában – holigen
4. Testnevelésösszevont csoportok (fiú/lány)igen
5. Csoportbontástechnika / informatika váltásigen
6. Osztályfőnökiki melyik osztály főnökeigen
7. Hittankötött órákha van
8. Napi sávokegyedi kérések (ki mikor tanít)ha kell
9–10. Szabályok, célfüggvényütközés, folytonosság, pontozásnem
11–12. Megoldás, HTMLfuttatás és megjelenítésnem

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ásMit jelentPélda
days=mely napokon tarthatjadays={PON, SRE, PET}
periods=hányadik órákbanperiods={1,2,3}
NO_FIRSTne legyen 1. órájaperiods=NO_FIRST
NO_SEVENTHne legyen 7. órájaperiods=NO_SEVENTH
több terema 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"}
Gyakori hiba

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.

Gyakorlati tanács

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
ÜzenetJelentése
OPTIMALMegvan 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.
INFEASIBLEA 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

OkPéldaMegoldá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

  1. Nézd meg, mit írt ki a program — a hibaüzenet felsorolja, mely beállításokat érdemes lazítani.
  2. Vedd ki az utoljára bevitt szabályt, és futtasd újra. Ha most megy, megvan a ludas.
  3. 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.
  4. 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.
Biztonsági háló

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.

MiCím
Python letöltéspython.org/downloads
Google OR-Toolsdevelopers.google.com/optimization
CP-SAT dokumentációCP-SAT megoldó bemutatása
OR-Tools forráskódgithub.com/google/or-tools
Notepad++notepad-plus-plus.org
Visual Studio Codecode.visualstudio.com