Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Tomorrow graphlib, Let us use everybody

Avatar for HayaoSuzuki HayaoSuzuki
September 27, 2025

Tomorrow graphlib, Let us use everybody

PyCon JP 2025 Day 1 Talk

Avatar for HayaoSuzuki

HayaoSuzuki

September 27, 2025
Tweet

More Decks by HayaoSuzuki

Other Decks in Technology

Transcript

  1. Who am I ? ͓લ୭Α Name Hayao Suzukiʢླ໦ɹॣʣ ///////// Twitter

    X @CardinalXaro Work ιϑτ΢ΣΞΤϯδχΞ at ౦ژΨεגࣜձࣾ ౦ژΨεגࣜձࣾʹ͍ͭͯ › Ұ౎࿡ݝʹ౎ࢢΨεɾిؾͳͲͷΤωϧΪʔΛڙڅ͢Δձࣾ › ౦ژΨε͸ PyCon JP 2025 ͷ Gold εϙϯαʔͰ͢ › ιϑτ΢ΣΞΤϯδχΞΛઈࢍืूத https://www.tokyo-gas-recruit.com/career/ 3 / 34
  2. Who am I ? ຋༁ › Effective Python ୈ 3

    ൛ (O’Reilly Japan) New! › ϋΠύʔϞμϯ Python(O’Reilly Japan) › Python Distilled(O’Reilly Japan) ؂༁ɾ؂म › ϩόετ Python(O’Reilly Japan) › ೖ໳ Python 3 ୈ 2 ൛ (O’Reilly Japan) › Python ΫΠοΫϦϑΝϨϯε ୈ 4 ൛ (O’Reilly Japan) 4 / 34
  3. Who am I ? աڈͷൃදʢൈਮʣ › Let’s implement useless Python

    objects(PyCon APAC 2023) › ૊ΈࠐΈؔ਺ pow ͷ஌ΒΕ͟ΔਐԽ (PyCon JP 2021) › ΠϯϝϞϦʔετϦʔϜ׆༻ज़ (PyCon JP 2020) › ܅͸ cmath Λ஌͍ͬͯΔ͔ (PyCon mini Shizuoka 2020) › Python ͱָ͠Ήॳ౳੔਺࿦ (PyCon mini Hiroshima 2019) › SymPy ʹΑΔ਺ࣜॲཧ (PyCon JP 2018) Ұཡ͸ https://xaro.hatenablog.jp/ Λࢀর͍ͯͩ͘͠͞ 5 / 34
  4. άϥϑͬͯɺԿʁ ఆٛ (ແ޲άϥϑ) ༗ݶू߹ V ͓Αͼ V ˆ V ͷඇॱংର͔ΒͳΔू߹ͷ෦෼ू߹

    E ͷ૊ G = (V; E) Λແ޲άϥϑͱݺͿɻ ఆٛ (༗޲άϥϑ) ༗ݶू߹ V ͓Αͼ V ˆ V ͷॱংର͔ΒͳΔू߹ͷ෦෼ू߹ E ͷ૊ G = (V; E) Λ༗޲άϥϑͱݺͿɻ › V Λ௖఺ू߹ɺE Λลू߹ͱݺͿɻ › V ͷཁૉΛ G ͷ௖఺ɺE ͷཁૉΛ G ͷลͱݺͿɻ 8 / 34
  5. τϙϩδΧϧιʔτͬͯɺԿʁ ఆٛ (ೋ߲ؔ܎) ू߹ A ͷ௚ੵ A ˆ A ͷ෦෼ू߹

    R Λೋ߲ؔ܎ͱݺͿɻ ·ͨɺ(a; b) 2 R Λ aRb ͱද͢ɻ ఆٛ (൒ॱংؔ܎) ҎԼͷੑ࣭Λຬͨؔ͢܎ R Λ൒ॱংؔ܎ͱݺͿɻ ൓ࣹ཯ 8a 2 A ʹରͯ͠ɺaRa Ͱ͋Δ ൓ରশ཯ a; b 2 A ʹରͯ͠ɺaRb ͔ͭ bRa ͳΒ͹ a = b Ͱ͋Δ ਪҠ཯ a; b; c 2 A ʹରͯ͠ɺaRb ͔ͭ bRc ͳΒ͹ aRc Ͱ͋Δ ൒ॱংؔ܎͸ɺେখؔ܎΍ൺֱͷ֓೦Λந৅ͨ͠΋ͷɻ 13 / 34
  6. τϙϩδΧϧιʔτͬͯɺԿʁ ఆٛ (ઢܕॱং) ू߹ A ͷ൒ॱংؔ܎ R ʹ͓͍ͯɺ8a; b 2

    A ʹରͯ͠ aRb ·ͨ͸ bRa ͕੒Γཱ ͭͳΒ͹ɺR ͸ઢܕॱংͰ͋ΔͱݺͿɻ ఆٛ (τϙϩδΧϧιʔτ) ༗޲άϥϑ G = (V; E) ͷτϙϩδΧϧιʔτͱ͸ɺV ͷઢܕॱং (V; ») Ͱɺ (u; v) 2 E ͳΒ͹ u » v Λຬͨ͢΋ͷͰ͋Δɻ 14 / 34
  7. τϙϩδΧϧιʔτͬͯɺԿʁ ఆٛ (าಓ) άϥϑ G = (V; E) ͷ௖఺ u1

    ͔Β uk ΁ͷ௕͞ k ͷาಓ W ͱ͸ɺ௖఺ͷྻ (u1 ; u2 ; : : : ; uk ) Ͱɺ(ui ; uj ) 2 E(1 » i < j » k) Λຬͨ͢΋ͷͰ͋Δɻಛ ʹɺu1 = uk ͷ৔߹ɺW ͸ด͍ͯ͡ΔͱݺͿɻ ఆٛ (ಓ) άϥϑ G = (V; E) ͷาಓ W ʹ͓͍ͯɺ௖఺͓Αͼล͕͢΂ͯҟͳΔ΋ͷ͸ಓͱݺ Ϳɻಛʹɺดͨ͡ಓΛด࿏ͱݴ͏ɻ ఆٛ (༗޲ඇ८ճάϥϑ) ༗޲άϥϑ G = (V; E) ʹ͓͍ͯɺด࿏Λؚ·ͳ͍΋ͷΛ༗޲ඇ८ճάϥϑͱݺͿɻ 15 / 34
  8. ָ͍͠ূ໌ίʔφʔ τϙϩδΧϧιʔτՄೳ ) ༗޲ඇ८ճάϥϑ. τϙϩδΧϧιʔτՄೳ͕ͩάϥϑ G ʹด࿏͕ଘࡏ͢ΔͱԾఆ͢Δɻ ͦͷด࿏Λ vi ;

    vj ; vk (i < j < k) ͱͯ͠ɺ͔ͭ vi » vj » vk ͱ͢Δɻ vi ; vj ; vk (i < j < k) ͸ด࿏ͳͷͰɺvk ͔Β vi ΁ͷล͕ଘࡏ͢Δɻ ͭ·Γɺvk » vi ͱͳΔ͕ɺͦΕ͸Ծఆ vi » vj » vk ʹໃ६͢Δɻ 17 / 34
  9. ·ͩ·ͩଓָ͍ͧ͘͠ূ໌ίʔφʔ ิ୊ ༗޲ඇ८ճάϥϑʹ͸ೖ࣍਺ 0 ͷ௖఺͕ඞͣଘࡏ͢Δɻ ূ໌. ༗޲ඇ८ճάϥϑͷ࠷௕ͷಓ v1 ; :

    : : ; vk Λ 1 ͭબͿɻv1 ʹೖΔล͕ଘࡏ͢ΔͳΒ ͹ɺu; v1 ; : : : ; vk ͔ͭ (u; v1 ) 2 E ͷΑ͏ͳ௖఺ u ͕ଘࡏ͢Δ͜ͱʹͳΔ͕ɺ v1 ; : : : ; vk ͕࠷௕ͷಓͰ͋Δͱ͍͏Ծఆʹ൓͢ΔɻΑͬͯɺv1 ͷೖ࣍਺͸ 0 ͱͳ Γɺ༗޲ඇ८ճάϥϑʹ͸ೖ࣍਺ 0 ͷ௖఺͕ඞͣଘࡏ͢Δɻ 18 / 34
  10. ͑ʁ ·ͩ͋ΔΜͰ͔͢ʁ ָ͍͠ূ໌ίʔφʔ ิ୊ ༗޲ඇ८ճάϥϑ G ͷ෦෼άϥϑ H ΋·ͨ༗޲ඇ८ճάϥϑͰ͋Δɻ ূ໌.

    ෦෼άϥϑ H ͕༗޲ඇ८ճάϥϑͰ͸ͳ͍ͱԾఆ͢ΔɻH ͷด࿏Λ C ͱͨ͠৔߹ɺ H ͸ G ͷ෦෼άϥϑͳͷͰɺด࿏ C ͸ G ʹ΋ଘࡏ͢Δ͜ͱʹͳΔɻ͔͠͠ɺͦΕ͸ G ͕༗޲ඇ८ճάϥϑͰ͋Δͱ͍͏Ծఆʹ൓͢Δɻ 19 / 34
  11. ָ͍͠Αͳʂ ূ໌ίʔφʔ ༗޲ඇ८ճάϥϑ ) τϙϩδΧϧιʔτՄೳ. ༗޲ඇ८ճάϥϑ G ʹ͸ඞͣೖ࣍਺ 0 ͷ௖఺͕ඞͣଘࡏ͢ΔͷͰɺͦͷ௖఺͓Αͼͦ

    ͔͜Βग़ΔลΛऔΓআ͘ɻऔΓআ͍ͨάϥϑ΋·ͨ༗޲ඇ८ճάϥϑͳͷͰɺ௖఺͕ͳ ͘ͳΔ·ͰͦΕΛ܁Γฦ͢ɻऔΓআ͍ͨॱ൪ʹ௖఺Λฒ΂ͨ΋ͷ͕τϙϩδΧϧιʔ τͰ͋Δɻ ॏཁɿূ໌͕ΞϧΰϦζϜʹͳ͍ͬͯΔ͜ͱʹ஫ҙɻ 20 / 34
  12. graphlib ͷ࢖͍ํ τϙϩδΧϧιʔτͷ࣮ߦ from graphlib import TopologicalSorter graph = {

    "D": {"B", "C"}, "C": {"A"}, "B": {"A"}, } order = TopologicalSorter(graph).static_order() print(f"Topological order: {" ˠ ".join(order)}") # A ˠ C ˠ B ˠ D D B, D C ͷΑ͏ͳΠϝʔδͰఆٛ͢Δɻ 27 / 34
  13. graphlib ͷ࢖͍ํ ༗޲ඇ८ճάϥϑͰ͸ͳ͍έʔε from graphlib import TopologicalSorter graph = {

    "A": {"C"}, "B": {"A"}, "C": {"B"} } order = TopologicalSorter(graph).static_order() print(f"Topological order: {" ˠ ".join(order)}") # graphlib.CycleError ͕ൃੜ͢Δ 28 / 34
  14. λεΫͷఆٛ dataclass ʹΑΔλεΫఆٛ @dataclass(frozen=True, slots=True) class Task: name: str action:

    Action deps: set[str] = field(default_factory=set) ௖఺͸ϋογϡՄೳͰ͋Δඞཁ͕͋ΔͷͰɺfrozen=True Λ࢖͏ɻ 30 / 34
  15. λεΫϥϯφʔ άϥϑͷఆٛ def run(tasks, max_workers=None): by_name = {t.name: t for

    t in tasks} ts = TopologicalSorter({t.name: set(t.deps) for t in ts.prepare() results: dict[str, object] = {} ... 31 / 34
  16. λεΫϥϯφʔ ฒߦॲཧɿεϨουʹ౤ೖ def run(tasks, max_workers=None): ... with ThreadPoolExecutor(max_workers) as pool:

    while ts.is_active(): ready = ts.get_ready() futs = {} for name in ready: print(f"run {name}") futs[pool.submit(by_name[name].action)] ... 32 / 34
  17. λεΫϥϯφʔ ฒߦॲཧɿ׬ྃ଴ͪ def run(tasks, max_workers=None): ... with ThreadPoolExecutor(max_workers) as pool:

    while ts.is_active(): ... for fut in as_completed(futs): name = futs[fut] results[name] = fut.result() print(f"done {name}") ts.done(name) return results 33 / 34
  18. ·ͱΊ ·ͱΊ › τϙϩδΧϧιʔτͱ͸ɺ༗޲ඇ८ճάϥϑͷ௖఺ू߹ͷઢܕॱংͰ͋Δɻ › ༗޲άϥϑ G ͕τϙϩδΧϧιʔτՄೳͰ͋ΔͨΊͷඞཁे෼৚݅͸ɺ ༗޲άϥϑ G

    ͕༗޲ඇ८ճάϥϑͰ͋Δ͜ͱͰ͋Δɻ › graphlib ͸ɺτϙϩδΧϧιʔτ͕࣮૷͞Εͨඪ४ϥΠϒϥϦͰ͋Δɻ › graphlib ͸ɺ؆қతͳλεΫϥϯφʔΛ࣮૷͢Δࡍʹɺ࣮ߦॱংΛܾఆ͢Δ ࢓૊Έͱͯ͠࢖͑Δɻ 34 / 34