GSoC 2019: Ṣiṣayẹwo awọn aworan fun ipinsimeji ati awọn oluyipada monad

Igba ooru to kọja Mo kopa ninu Ooru Google ti Koodu - eto fun awọn ọmọ ile-iwe lati Google. Ni gbogbo ọdun, awọn oluṣeto yan ọpọlọpọ awọn iṣẹ akanṣe Orisun Orisun, pẹlu lati iru awọn ajọ olokiki daradara bi Igbelaruge.org и Ipilẹ Linux. Google n pe awọn ọmọ ile-iwe lati gbogbo agbala aye lati ṣiṣẹ lori awọn iṣẹ akanṣe wọnyi. 

Gẹgẹbi alabaṣe kan ninu Google Summer of Code 2019, Mo ṣe iṣẹ akanṣe laarin ile-ikawe naa Alga pẹlu ajo Haskell.org, eyiti o n ṣe idagbasoke ede Haskell - ọkan ninu awọn ede siseto iṣẹ ṣiṣe olokiki julọ. Alga ni a ìkàwé ti o duro iru ailewu aṣoju fun awọn aworan ni Haskell. O ti wa ni lilo, fun apẹẹrẹ, ni titẹle - ile-ikawe Github kan ti o kọ awọn igi atunmọ, ipe ati awọn aworan igbẹkẹle ti o da lori koodu ati pe o le ṣe afiwe wọn. Ise agbese mi ni lati ṣafikun iru-ailewu oniduro fun awọn aworan ipin-meji ati awọn algoridimu fun aṣoju yẹn. 

Ninu ifiweranṣẹ yii Emi yoo sọrọ nipa imuse mi ti algorithm kan fun ṣayẹwo iwọn kan fun ipinsimeji ni Haskell. Paapaa botilẹjẹpe algoridimu jẹ ọkan ninu ipilẹ julọ, imuse rẹ ni ẹwa ni ara iṣẹ ṣiṣe mu mi ni ọpọlọpọ awọn iterations ati nilo iṣẹ lọpọlọpọ. Bi abajade, Mo yanju lori imuse pẹlu awọn oluyipada monad. 

GSoC 2019: Ṣiṣayẹwo awọn aworan fun ipinsimeji ati awọn oluyipada monad

Nipa ara mi

Orukọ mi ni Vasily Alferov, Mo jẹ ọmọ ile-iwe ọdun kẹrin ni St. Sẹyìn ninu awọn bulọọgi ti mo ti kowe nipa mi ise agbese nipa parameterized aligoridimu и nipa irin ajo lọ si ZuriHac. Ni bayi Mo wa lori ikọṣẹ ni Yunifasiti ti Bergen ni Norway, nibiti Mo n ṣiṣẹ lori awọn ọna si iṣoro naa Awọ Akojọ. Awọn iwulo mi pẹlu awọn algoridimu parameterized ati siseto iṣẹ.

Nipa imuse ti algorithm

Ọrọ iṣaaju

Awọn ọmọ ile-iwe ti o kopa ninu eto naa ni iwuri pupọ lati buloogi. Wọn fun mi ni ipilẹ kan fun bulọọgi naa Ooru ti Haskell. Nkan yii jẹ itumọ awọn nkan, ti a kọ nipasẹ mi nibẹ ni Oṣu Keje ni ede Gẹẹsi, pẹlu ọrọ-ọrọ kukuru kan. 

Fa Ibere ​​pẹlu koodu ni ibeere le ṣee ri nibi.

O le ka nipa awọn abajade iṣẹ mi (ni ede Gẹẹsi) nibi.

Ifiweranṣẹ yii jẹ ipinnu lati mọ oluka naa pẹlu awọn imọran ipilẹ ni siseto iṣẹ, botilẹjẹpe Emi yoo gbiyanju lati ranti gbogbo awọn ofin ti a lo nigbati akoko ba de.

Ṣiṣayẹwo awọn aworan fun ipinsimeji 

Algoridimu kan fun ṣiṣayẹwo iwọn kan fun ipinsimeji ni igbagbogbo ni a fun ni iṣẹ-ẹkọ lori awọn algoridimu bi ọkan ninu awọn algoridimu ayaworan ti o rọrun julọ. Ero rẹ jẹ taara: akọkọ a bakan fi awọn inaro si apa osi tabi ọtun, ati nigbati a ba rii eti ti o fi ori gbarawọn, a sọ pe iyaya naa kii ṣe ipin.

Awọn alaye diẹ sii: akọkọ a fi diẹ ninu awọn fatesi sinu ipin osi. O han ni, gbogbo awọn aladugbo ti vertex yii gbọdọ dubulẹ ni lobe ọtun. Siwaju sii, gbogbo awọn aladugbo ti awọn aladugbo ti vertex yii gbọdọ dubulẹ ni lobe osi, ati bẹbẹ lọ. A tesiwaju a pin mọlẹbi to vertices bi gun bi nibẹ ni o wa si tun vertices ni awọn ti sopọ paati fatesi ti a bere pẹlu ti a ko ti yàn awọn aladugbo. A tun ṣe iṣẹ yii fun gbogbo awọn paati ti a ti sopọ.

Ti eti ba wa laarin awọn inaro ti o ṣubu sinu ipin kanna, ko ṣoro lati wa ọmọ aibikita ninu ayaworan naa, eyiti o jẹ olokiki pupọ (ati pe o han gedegbe) ko ṣee ṣe ni iwọn ipin-meji. Bibẹẹkọ, a ni ipin ti o pe, eyiti o tumọ si pe aworan naa jẹ ipin-meji.

Ni deede, a ṣe imuse algorithm yii ni lilo ibú akọkọ search tabi ijinle akọkọ search. Ni awọn ede ti o ṣe pataki, wiwa-jinle akọkọ ni a maa n lo bi o ṣe rọrun diẹ ati pe ko nilo awọn ẹya data afikun. Mo tun yan ijinle-akọkọ wiwa bi o ṣe jẹ aṣa diẹ sii.

Nitorinaa, a wa si eto atẹle naa. A kọja awọn inaro ti awọn iwọn nipa lilo ijinle-akọkọ wiwa ati fi awọn ipin si wọn, yiyipada nọmba ipin naa bi a ti nlọ ni eti. Bí a bá gbìyànjú láti pín ìpín kan sí ìforígbá tí ó ti ní ìpín kan tí a yàn tẹ́lẹ̀, a lè sọ láìfọ̀rọ̀ sábẹ́ ahọ́n sọ pé àwòrán náà kì í ṣe alápá méjì. Awọn akoko gbogbo vertices ti wa ni sọtọ a pin ati awọn ti a ti sọ wò ni gbogbo awọn egbegbe, a ni kan ti o dara ipin.

Ti nw ti isiro

Ni Haskell a ro pe gbogbo awọn iṣiro jẹ mọ. Sibẹsibẹ, ti eyi ba jẹ ọran nitootọ, a kii yoo ni ọna lati tẹ ohunkohun si iboju. Rara, mọ awọn iṣiro jẹ ọlẹ ti ko si ọkan mọ awọn idi lati ṣe iṣiro nkan kan. Gbogbo awọn iṣiro ti o waye ninu eto naa ni a fi agbara mu bakan sinu "alaimọ" monad IO.

Monads jẹ ọna lati ṣe aṣoju awọn iṣiro pẹlu awọn ipa ni Haskell. Ṣalaye bi wọn ṣe n ṣiṣẹ kọja aaye ti ifiweranṣẹ yii. Apejuwe ti o dara ati kedere ni a le ka ni Gẹẹsi nibi.

Nibi Mo fẹ tọka si pe lakoko ti diẹ ninu awọn monads, gẹgẹ bi IO, ti wa ni imuse nipasẹ idan alakojọ, o fẹrẹ jẹ gbogbo awọn miiran ni imuse ni sọfitiwia ati gbogbo awọn iṣiro ninu wọn jẹ mimọ.

Awọn ipa pupọ lo wa ati ọkọọkan ni monad tirẹ. Eyi jẹ ilana ti o lagbara pupọ ati ẹlẹwa: gbogbo awọn monads ṣe imuse wiwo kanna. A yoo sọrọ nipa awọn monads mẹta wọnyi:

  • Boya ea jẹ iṣiro kan ti o da iye ti iru a pada tabi da sile iru e. Iwa ti monad yii jọra pupọ si mimu imukuro ni awọn ede pataki: awọn aṣiṣe le mu tabi kọja. Iyatọ akọkọ ni pe monad ti ni imuse pẹlu ọgbọn ni kikun ni ile-ikawe boṣewa ni Haskell, lakoko ti awọn ede pataki nigbagbogbo lo awọn ẹrọ ṣiṣe.
  • State sa ni a isiro ti o pada a iye ti iru a ati ki o ni wiwọle si mutable ipinle ti iru s.
  • Boya a. Boya monad n ṣalaye iṣiro kan ti o le ni idilọwọ ni eyikeyi akoko nipa dapadabọ Nkankan. Sibẹsibẹ, a yoo sọrọ nipa imuse ti kilasi MonadPlus fun oriṣi Boya, eyiti o ṣe afihan ipa idakeji: o jẹ iṣiro kan ti o le ni idilọwọ ni eyikeyi akoko nipa pada iye kan pato.

Imuse ti alugoridimu

A ni awọn oriṣi data meji, Graph a ati Bigraph ab, akọkọ eyiti o ṣe aṣoju awọn aworan pẹlu awọn inaro ti a samisi pẹlu awọn iye ti iru a, ati pe keji jẹ aṣoju awọn aworan ipin-meji pẹlu awọn inaro apa osi ti aami pẹlu awọn iye ti iru a ati ọtun -awọn igun ẹgbẹ ti aami pẹlu awọn iye ti iru b.

Iwọnyi kii ṣe awọn oriṣi lati ile-ikawe Alga. Alga ko ni aṣoju fun awọn aworan ipin-meji ti a ko daa. Mo ti ṣe awọn iru bi yi fun wípé.

A yoo tun nilo awọn iṣẹ oluranlọwọ pẹlu awọn ibuwọlu wọnyi:

-- Список соседей данной вершины.
neighbours :: Ord a => a -> Graph a -> [a]

-- Построить двудольный граф по графу и функции, для каждой вершины
-- выдающей её долю и пометку в новой доле, игнорируя конфликтные рёбра.
toBipartiteWith :: (Ord a, Ord b, Ord c) => (a -> Either b c)
                                         -> Graph a
                                         -> Bigraph b c

-- Список вершин в графе
vertexList :: Ord a => Graph a -> [a]
Сигнатура функции, которую мы будем писать, выглядит так:

type OddCycle a = [a]
detectParts :: Ord a => Graph a -> Either (OddCycle a) (Bigraph a a)

O rọrun lati rii pe ti o ba jẹ pe lakoko wiwa-akọkọ ti o jinlẹ ti a rii eti ti o fi ori gbarawọn, yiyipo aiṣedeede wa lori oke akopọ atunwi naa. Nitorinaa, lati mu pada, a nilo lati ge ohun gbogbo kuro lati akopọ isọdọtun titi di iṣẹlẹ akọkọ ti fatesi to kẹhin.

A ṣe ìṣàwárí ìjìnlẹ̀ àkọ́kọ́ nípa títọ́jú àkópọ̀ àkópọ̀ àwọn nọ́ńbà ìpín fún ọ̀kọ̀ọ̀kan. Akopọ atunkọ yoo wa ni itọju laifọwọyi nipasẹ imuse ti kilasi Functor ti monad ti a ti yan: a yoo nilo nikan lati fi gbogbo awọn inaro lati ọna sinu abajade ti o pada lati iṣẹ atunṣe.

Ero akọkọ mi ni lati lo boya monad, eyiti o dabi pe o ṣe awọn ipa ti a nilo ni deede. Ipilẹṣẹ akọkọ ti Mo kowe jẹ isunmọ si aṣayan yii. Ni otitọ, Mo ni awọn imuse oriṣiriṣi marun ni aaye kan ati nikẹhin gbe lori ọkan miiran.

Lákọ̀ọ́kọ́, a ní láti tọ́jú àkópọ̀ àkópọ̀ àwọn olùdámọ̀ ìpín – èyí jẹ́ nǹkankan nípa Ìpínlẹ̀. Ni ẹẹkeji, a nilo lati ni anfani lati da duro nigbati ija kan ba rii. Eyi le jẹ boya Monad fun Boya, tabi MonadPlus fun Boya. Iyatọ akọkọ ni pe boya o le pada iye kan ti iṣiro naa ko ba ti duro, ati boya o pada alaye nikan nipa eyi ninu ọran yii. Niwon a ko nilo kan lọtọ iye fun aseyori (o ti wa ni tẹlẹ ti o ti fipamọ ni State), a yan Boya. Ati ni akoko ti a nilo lati darapọ awọn ipa ti awọn monads meji, wọn jade monad Ayirapada, eyiti o dapọ awọn ipa wọnyi ni deede.

Kini idi ti MO yan iru iru eka kan? Idi meji. Ni akọkọ, imuse naa yoo jẹ iru pupọ si pataki. Keji, a nilo lati se afọwọyi awọn ipadabọ iye ni irú ti rogbodiyan nigba ti pada pada lati recursion lati mu pada awọn odd lupu, eyi ti o jẹ Elo rọrun lati ṣe ni boya monad.

Bayi a gba imuse yii.

{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE ScopedTypeVariables #-}

data Part = LeftPart | RightPart

otherPart :: Part -> Part
otherPart LeftPart  = RightPart
otherPart RightPart = LeftPart

type PartMap a = Map.Map a Part
type OddCycle a = [a]

toEither :: Ord a => PartMap a -> a -> Either a a
toEither m v = case fromJust (v `Map.lookup` m) of
                    LeftPart  -> Left  v
                    RightPart -> Right v

type PartMonad a = MaybeT (State (PartMap a)) [a]

detectParts :: forall a. Ord a => Graph a -> Either (OddCycle a) (Bigraph a a)
detectParts g = case runState (runMaybeT dfs) Map.empty of
                     (Just c, _)  -> Left  $ oddCycle c
                     (Nothing, m) -> Right $ toBipartiteWith (toEither m) g
    where
        inVertex :: Part -> a -> PartMonad a
        inVertex p v = ((:) v) <$> do modify $ Map.insert v p
                                      let q = otherPart p
                                      msum [ onEdge q u | u <- neigbours v g ]

        {-# INLINE onEdge #-}
        onEdge :: Part -> a -> PartMonad a
        onEdge p v = do m <- get
                        case v `Map.lookup` m of
                             Nothing -> inVertex p v
                             Just q  -> do guard (q /= p)
                                           return [v]

        processVertex :: a -> PartMonad a
        processVertex v = do m <- get
                             guard (v `Map.notMember` m)
                             inVertex LeftPart v

        dfs :: PartMonad a
        dfs = msum [ processVertex v | v <- vertexList g ]

        oddCycle :: [a] -> [a]
        oddCycle c = tail (dropWhile ((/=) last c) c)

Ibi ti Àkọsílẹ jẹ mojuto ti algorithm. Emi yoo gbiyanju lati ṣalaye ohun ti n ṣẹlẹ ninu rẹ.

  • inVertex jẹ apakan ti wiwa ijinle-akọkọ nibiti a ti ṣabẹwo si fatesi fun igba akọkọ. Nibi ti a pin nọmba ipin si fatesi ati ṣiṣe awọn onEdge lori gbogbo awọn aladugbo. Eleyi jẹ tun ibi ti a mu pada akopọ ipe: ti o ba ti msum pada a iye, a Titari fatesi v wa nibẹ.
  • onEdge jẹ apakan ti a ṣabẹwo si eti. O ti wa ni a npe ni lemeji fun kọọkan eti. Nibi ti a ṣayẹwo ti o ba ti fatesi ni apa keji ti a ti ṣàbẹwò, ki o si be o ti o ba ko. Ti o ba ṣabẹwo si, a ṣayẹwo boya eti naa jẹ ikọlura. Ti o ba jẹ bẹ, a da iye pada - oke pupọ ti akopọ isọdọtun, nibiti gbogbo awọn ila miiran yoo wa ni gbe lori ipadabọ.
  • ProcessVertex sọwedowo fun kọọkan fatesi boya o ti a ti ṣàbẹwò ati ki o nṣiṣẹ inVertex lori rẹ ti o ba ko.
  • dfs nṣiṣẹ ilanaVertex lori gbogbo awọn aaye.

Gbogbo ẹ niyẹn.

Itan-akọọlẹ ti ọrọ INLINE

Ọrọ INLINE ko si ni imuse akọkọ ti algoridimu; o han nigbamii. Nigbati Mo gbiyanju lati wa imuse to dara julọ, Mo rii pe ẹya ti kii ṣe INLINE jẹ akiyesi losokepupo lori diẹ ninu awọn aworan. Ṣiyesi pe ni itumọ ti awọn iṣẹ yẹ ki o ṣiṣẹ kanna, eyi ya mi lẹnu pupọ. Paapaa alejò, lori ẹrọ miiran pẹlu ẹya ti o yatọ ti GHC ko si iyatọ ti o ṣe akiyesi.

Lẹhin lilo ọsẹ kan kika iṣelọpọ GHC Core, Mo ni anfani lati ṣatunṣe iṣoro naa pẹlu laini kan ti INLINE ti o fojuhan. Ni diẹ ninu awọn aaye laarin GHC 8.4.4 ati GHC 8.6.5 optimizer duro ṣe eyi lori ara rẹ.

Emi ko nireti lati pade iru idoti bẹ ni siseto Haskell. Sibẹsibẹ, paapaa loni, awọn olupilẹṣẹ nigbakan ṣe awọn aṣiṣe, ati pe o jẹ iṣẹ wa lati fun wọn ni imọran. Fun apẹẹrẹ, nibi a mọ pe iṣẹ naa yẹ ki o wa ni itọka nitori pe o wa ni itọka ninu ẹya pataki, ati pe eyi jẹ idi kan lati fun olupilẹṣẹ ni itọka.

Kí ló ṣẹlẹ lẹ́yìn náà?

Lẹhinna Mo ṣe imuse Hopcroft-Karp algorithm pẹlu awọn monads miiran, ati pe iyẹn ni opin eto naa.

Ṣeun si Google Summer of Code, Mo ni iriri ti o wulo ni siseto iṣẹ-ṣiṣe, eyiti kii ṣe iranlọwọ nikan fun mi lati gba ikọṣẹ ni Jane Street ni igba ooru ti o tẹle (Emi ko ni idaniloju bi ibi yii ṣe mọ daradara paapaa laarin awọn olugbo oye Habr, ṣugbọn o jẹ ọkan. ti awọn diẹ ni ibi ti o le ooru lati olukoni ni iṣẹ siseto), sugbon tun ṣe mi si awọn iyanu aye ti a lilo yi paradigm ni asa, significantly o yatọ lati mi iriri ni ibile ede.

orisun: www.habr.com

Fi ọrọìwòye kun