Multihalmaz és megvalósítása

A konténerobjektumok alapvető megkülönböztető jellemzői, hogy számít-e a bennük foglalt elemek sorrendje és az, hogy megengedett-e, hogy ugyanazon elem többször előforduljon. Ez a két feltétel négy konténerkategóriát határoz meg. Ezt mutatja az ábra, ahol a Python releváns beépített alaptípusai vannak besorolva az egyes kategóriákba.

Láthatjuk, hogy abban a konténerkategóriában, amelynél az elemek sorrendje nem jellemző, viszont ugyanazon elem többször is előfordulhat nem szerepel beépített konténertípus. Ezt a kategóriát multihalmaznak (multiset) nevezik a matematikában. Ez az elnevezés lényegében arra utal arra, hogy az ilyen konténerobjektum sok tekintetben hasonlít a halmazokra, de eltér abban, hogy lehet benne elemismétlődés.

A multihalmaz tehát abban különbözik a halmaztól (set), hogy megenged azonos elemeket is, azaz egy adott elem nem csak legfeljebb 1-szer fordulhat elő, mint egy normál halmazban, hanem többször is.

Multihalmazzal számos olyan valós helyzet és feladat modellezhető, amelyek halmazzal vagy sorozattal nem, vagy csak nehézkesen. Ilyen például egy dobozban levő tárgyak sokasága, amelyek között van egyforma (pl. a kombinatorikában szinte mindig megemlített valamilyen darabszámú piros és fehér golyók); egy bevásárló kosár tartalma, ahol ugyanazon árucikkből több darabot is vehetünk. Vagy akár a molekulák, hiszen azok atomok olyan sokasága, amelyek között ugyanaz többször szerepelhet egy molekulában.

A multihalmazzal való munkához szükséges annak alapjellemzőit megismerni. Ezek röviden összefoglalva a következők.

  • Egy multihalmaz akkor adott, ha ismertek az elemei és, hogy azok hányszor fordulnak elő.
  • A multihalmaz egy elemének multiplicitása (multiplicity) az a pozitív egész szám, ahányszor az adott elem előfordul, ismétlődik. A multihalmazok között végzett műveletek nulla vagy negatív multiplicitást is eredményezhetnek. Azonban egy objektum csak akkor eleme a multihalmaznak, ha multiplicitása pozitív.
  • A multihalmaz elemszáma vagy számossága (cardinality) az elemei multiplicitásának összege. Ha a számosság nulla, akkor üres multihalmazról van szó.
  • Egy A multihalmaz részmultihalmaza (submultiset) egy olyan multihalmaz, amelynek minden eleme A-nak is eleme és multiplicitásuk legfeljebb akkora, mint az A-ban szereplő multiplicitás.
  • Egy A multihalmaz valódi részmultihalmaza (proper submultiset) egy olyan multihalmaz, amelynek minden eleme A-nak is eleme és multiplicitásuk kisebb, mint az A-ban szereplő multiplicitás.

A multihalmazok között a normál halmazokra vonatkozó alapműveletek (unió, metszet, különbség, szimmetrikus különbség) szintén értelmezettek, de általánosított módon a következő definíciók szerint:

Az A és B multihalmaz

– uniója (union) az a legkisebb számosságú multihalmaz, amelynek mind A, mind B részhalmaza. Ebből következik, hogy az unióban szereplő bármely x elem multiplicitása az A és B multihalmazokban szereplő x elemek multiplicitásai közül a nagyobb.

– metszete (intersection) az a legnagyobb számosságú multihalmaz, amely mind az A, mind a B multihalmaznak részhalmaza. Ebből következik, hogy a metszetben szereplő bármely x elem multiplicitása az A és B multihalmazokban szereplő x elemek multiplicitásai közül a kisebb.

– különbsége (difference) egy olyan multihalmaz, amelyben egy adott elem multiplicitása az elem A-beli és B-beli multiplicitásának különbsége, ha az pozitív, és nulla egyébként.

– szimmetrikus különbsége (symmetric difference) az a multihalmaz, amely A és B uniójának és metszetének különbsége.

Eltérően a normál halmazoktól, a multihalmazok között értelmezett még az összegzés (sum) művelete is, amely egy olyan multihalmazt eredményez, amelyben egy elem multiplicitása az adott elem A-beli és B-beli multiplicitásainak összege.

Ezen alapműveleteket szemlélteti a következő ábra a szokásos matematikai műveleti jelekkel.

Ha multihalmazokkal szeretnénk a programunkban dolgozni, akkor kell egy erre alkalmas konténertípus. Ahogy fentebb említettük, sztenderd beépített típus erre nincs a Pythonban, de a kategorizálást mutató ábrán jeleztük, hogy a collections modulban található Counter osztály – bár a neve nem utal rá – alkalmazható lehet erre. Mindazonáltal a Counter osztálynak ebből a szempontból megvannak a maga korlátai. Például nem kínálja fel a set és frozetset típusoknál elérhető halmazműveleteket (unió, metszet, különbség, szimmetrikus különbség) megvalósító metódusokat; ezek a műveletek csak operátorral valósíthatók meg, kivéve a szimmetrikus különbséget, mert a ^ operátor, illetve a __xor__ metódus nincs értelmezve. Ráadásul ezek az operátorok is csak Counter típusok között működnek, holott lenne értelme halmazműveleteknek multihalmaz és halmaz között is, hiszen egy normál halmaz felfogható úgy, mint egy olyan multihalmaz, amelyben az elemek multiplicitása 1.

Mindezen okból érdemes lehet elkészíteni egy Multiset nevű osztályt, amely rendelkezik egy multihalmaztól elvárható képességekkel. Azért is lehet hasznos egy ilyen osztály felépítésén gondolkodni és dolgozni, mert ennek során nem csak a multihalmazokkal van alkalmunk mélyrehatóbban megismerkedni, hanem Python tudásunkat is jelentősen fejleszthetjük, mert az osztály létrehozásához jónéhány nyelvi elem és konstrukció ismerete szükséges.

Mivel a Counter osztály számos, multihalmazra jellemző attribútummal és képességgel rendelkezik, célszerű ezt kihasználni. Ezért a Multiset oszályunk a Counter osztályt örökli. A Multiset osztály egy lehetséges osztálydefinícióját alább láthatjuk. A kommentek segítik a megértést. /A működéshez Python 3.10+ szükséges/

A multihalmazok alkalmazására, a közöttük végrehajtható műveletekre (unió, metszet, különbség és összegzés) mutatunk pár példát a következőkben az elkészített Multiset típus használatával:

E bejegyzésben szereplő főbb nyelvi elemekről a Python tudásépítés lépésről lépésre című e-könyv következő részeiben olvashatunk részleteiben: „Beépített típusok nyilvános metódusai” fejezet „Halmazműveletek” alfejezet. Az „Osztály vigyázz! – típuslétrehozás osztályokkal”, az „Öröklődés” és a „Mágikus metódusok egyedi igényre szabott osztályokban” című fejezetek. Továbbá a „Készétel fogyasztás – a szabványos könyvtár moduljainak használata” fejezet „Speciális konténer típusok” alfejezet „Sorozatelemek összeszámolása – Counter” címe.

Érdekel a Python tudásépítés lépésről lépésre az alapoktól az első asztali alkalmazásig című e-könyv.