モノむドずその応甚朚でのモノむド蚈算

ご挚拶、Habrahabr。 今日、私はい぀ものスタむルで、コミュニティにデヌタ構造に関する小さな教育プログラムを提䟛したいず思っおいたす。 今回だけ、より包括的になり、そのアプリケヌションず実甚性は、プログラミングの最も倚様な分野にたで広がりたす。 もちろん、最も矎しいアプリケヌションに぀いおは、蚘事で盎接瀺しお説明したす。



抜象的思考のドロップ、バランスのずれた怜玢ツリヌたずえば、前述のデカルトツリヌ の知識、単玔なCコヌドの読み取り胜力、埗られた知識を適甚したいずいう欲求が必芁です。



そのため、今日の議題には、 モノむドず、蚈算をツリヌにキャッシュするための䞻なアプリケヌションがありたす。



抂念ずしおのモノむド



倚数のもの 、぀たり操䜜する倚数のオブゞェクトを想像しおください。 Mず呌びたしょう。 このセットでは、バむナリ挔算、぀たり、新しい芁玠をセットの芁玠のペアに関連付ける関数を導入したす。 以䞋、この抜象操䜜を「⊗」で衚し、匏を䞭眮圢匏で蚘述したす。aずbがセットの芁玠である堎合、 c = a⊗bもこのセットの芁玠です。



たずえば、䞖界に存圚するすべおの線を考えおみたしょう。 たた、文字列連結操䜜に぀いお考えおみ"JohnDoe"



。これは、数孊では䌝統的に「◊」ず呌ばれ、ほずんどのプログラミング蚀語では「+」 "John"



◩ "Doe"



= "JohnDoe"



です。 ここで、セットMは文字列であり、◊オペレヌションasずしお機胜したす。

たたは、タプルを操䜜するずきに関数型蚀語で知られおいるfst関数もありたす。 圌女は2぀の匕数のうち、結果ずしお最初の匕数を順番に返したす。 したがっお、 fst  5、2 = 5 ; fst  "foo"



、 "bar"



= "foo"



。 この2項挔算をどのセットで考慮するかは問題ではないため、いずれを遞択するかはナヌザヌの遞択です。



次に、操䜜「⊗」に結合性制玄を課したす。 これは、以䞋を必芁ずするこずを意味したす。「⊗」を䜿甚する堎合、オブゞェクトのシヌケンスが結合されるず、「⊗」の適甚順序に関係なく、結果は同じたたになりたす。 より厳密には、 任意の 3぀のオブゞェクトa 、 b 、およびcに぀いお、次のようになりたす。

a⊗b⊗c = a⊗b⊗c

文字列の連結が連想的であるこずは簡単にわかりたす。文字列シヌケンスのどの接着が先に行われ、埌でどの接着が行われおも、シヌケンス内のすべおの文字列の共通の接着が埗られたす。 同じこずが関数fstにも圓おはたりたす。

fst  fst  a 、 b 、 c = a

fst  a 、 fst  b 、 c = a

シヌケンスぞのfstアプリケヌションのチェヌンは、任意の順序で匕き続きヘッド芁玠を生成したす。



そしお最埌に必芁なこずは、操䜜に関する集合Mには、 䞭立芁玠たたは操䜜単䜍が存圚する必芁があるこずです。 これは、セットの任意の芁玠ず組み合わせるこずができるオブゞェクトであり、セットを倉曎するこずはありたせん。 正匏に蚀えば、 eが䞭立芁玠である堎合、セットのaに぀いおは 、

a⊗e = e⊗a = a

線のある䟋では、ニュヌトラル芁玠は空の線""



です。どちらの線に貌り付けおも、線は倉わりたせん。 しかし、この点でのfstは私たちに適しおいたす。䞭立的な芁玠を考え出すこずは䞍可胜です。 実際、 fst  e 、 a = eは垞にeであり、 a ≠ eの堎合、䞭立性は倱われたす。 もちろん、1぀の芁玠のセットでfstを怜蚎できたすが、そのような退屈を必芁ずするのは誰ですか :)



そのような各トリプル<M、⊗、e>は、 モノむドず厳soleに呌ばれたす。 コヌドでこの知識を修正したす。

 public interface IMonoid<T> { T Zero { get; } T Append(T a, T b); }
      
      





モノむドのより倚くの䟋、および実際にそれらを䜿甚する堎所は、カットの䞋にありたす。





䟋





先に進む前に、読者に䞖界に闇があり、さたざたなモノむドをあいたいにしおいるこずを玍埗させる必芁がありたす。 そのうちのいく぀かをテキストの埌半で䟋ずしお䜿甚したすが、実際には読者が遭遇するものもありたす。 各モノむドに察しお、問題のセット、組み合わせ操䜜、ニュヌトラル芁玠を瀺す簡単なリストを䜜成したす。 すべおの操䜜の関連性をご自身で確認しおください。ここには十分なスペヌスがありたせん。さらに、少しカンニングしたす。たた、次の蚘事では章党䜓を取り䞊げるので、最も興味深い、異垞なモノむドをリストに含めたせん。



したがっお、人気のあるモノむド



これに぀いおは、今すぐ䟋を終了しお緎習に移りたしょう。 この埅望のプラクティスを実際に玹介する前に、このリストからいく぀かの単玔なモノむドの定矩をCで蚘述したす。これに぀いおは次の章で扱いたす。

すべおのモノむドをシングルトヌンずしお実装したす。 埌で䞍明なモノむドタむプのむンスタンスにアクセスしやすくするために、その䜜成を別の静的クラスに入れたした。


 public static class Singleton<T> where T : new() { private static readonly T _instance = new T(); public static T Instance { get { return _instance; } } } public class AddMonoid : IMonoid<int> { public AddMonoid() {} public int Zero { get { return 0; } } public int Append(int a, int b) { return a + b; } } public class FunctionMonoid<T> : IMonoid<Func<T, T>> { public FunctionMonoid() {} public Func<T, T> Zero { get { return x => x; } } public Func<T, T> Append(Func<T, T> f, Func<T, T> g) { return x => g(f(x)); } } public class GCDMonoid : IMonoid<int> { public GCDMonoid() {} private int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } public int Zero { get { return 0; } } public int Append(int a, int b) { return gcd(a, b); } }
      
      







コンピュヌタサむ゚ンスのどこでロヌプ





この瞬間から、私たちは実甚的なアプリケヌションの分野に入りたす。



たず、 Ropeずいうデヌタ構造定矩が必芁です。 たれなロシア語の情報源は、苊劎せずにそれをロヌプのように翻蚳したす。私はこの䌝統から匕き䞋げたせん。 したがっお、ロヌプは、远加機胜を備えた䞍倉文字列の䟿利な実装ずしお、1995幎に最初に提案されたした。たずえば、郚分文字列を取埗しお文字列をマヌゞする非垞に高速な操䜜です。 このような目的のために、この構造は、たずえばJavaラむブラリで匕き続き䜿甚されたす。



任意の平衡二分朚を想像しおください。 このツリヌの葉ずしお蚀葉を掛けたす-぀たり 文字の配列。 結果のツリヌは、たずえば次のようになりたす。



このようなデヌタ構造はロヌプず呌ばれたす。



むンデックスアクセス


デカルトツリヌに関する以前の蚘事から、このようなツリヌでむンデックスによるシンボルク゚リの決定がどのように可胜かを芚えおいたす-サブツリヌを䞭間頂点に栌玍するだけで十分です。この堎合、サブツリヌから䞭断された文字列の党長です。 このツリヌの堎合、同様のスキヌムは次のようになりたす。



ここで、K番目の順序統蚈の䜿い慣れたアルゎリズムを䜿甚しお、目的の番号の䞋の文字を含む配列に移動し、配列のメモリ内で盎接むンデックスを䜜成しお目的の文字を返すこずができたす。 倧きな行でのメモリ最適化ず小さな行でのパフォヌマンスの理由だけで、個々の文字ではなくツリヌの葉で配列が䞭断されおいるこずに泚意しおください。



接着


2本のロヌプを接着するには、新しいルヌト頂点を䜜成し、2぀のデヌタツリヌを息子ずしおサスペンドするだけで十分です。 ゜ヌスツリヌのバランスが取れおいるため、新しいロヌプもバランスが取れたす。 圌らはたた、接着されたロヌプが小さすぎるかどうか、結果ずしお埗られるロヌプでいく぀かのリヌフセグメントを組み合わせるこずが理にかなっおいるかどうかをよく調べたす。



郚分文字列リク゚スト


文字列内の郚分文字列を遞択するには、K番目の順序統蚈に類䌌した単玔なアルゎリズムを適甚するだけで十分です。 ロヌプTの開始文字から始たる長さlenの郚分文字列を遞択する必芁があるずしたす。



最初に、2぀の極端なケヌスを考えたす。

start = 0



か぀len = T.Left.Size



堎合、答えはT.Left



サブツリヌ党䜓T.Left



。 同様に、 start = T.Left.Size



、およびlen = T.Right.Size



堎合、答えはT.Right



サブツリヌ党䜓T.Right



。 䞊の図では、2番目のケヌスはSubstring( start : 18, len : 37)



関数Substring( start : 18, len : 37)



を呌び出すず実珟され、関数は必芁な郚分文字列" , "



正しいサブツリヌをすぐに返したす。



さらに、目的の郚分文字列が完党に巊のサブツリヌにある堎合、぀たりstart < T.Left.Size



でstart + len ≀ T.Left.Size



start < T.Left.Size



の堎合も可胜start + len ≀ T.Left.Size



。 次に、巊のサブツリヌに察しおサブストリング怜玢関数を再垰的に呌び出す必芁がありたす。

察称の堎合は、完党に右偎のサブツリヌにある郚分文字列です。぀たり、 start ≥ T.Left.Size



、 start + len ≀ T.Left.Size + T.Right.Size



です。 次に、再垰怜玢は右のサブツリヌに進みたす。巊のサブツリヌのサむズをstart



から枛算するこずを忘れないでください。結局、右のサブツリヌのむンデックス䜜成はれロから始たり、独立したツリヌず芋なされたす。

この䟋では、 Substring( start : 18, len : 18)



呌び出すこずができたす。 次に、最初のステップで、関数は再垰的に右にSubstring( start : 0, len : 18)



お、右のサブツリヌSubstring( start : 0, len : 18)



を呌び出す必芁があるず刀断したす。 そしお、圌は、最初のケヌスに埓っお、 " , "



郚分文字列に察応する、圌の巊のサブツリヌ党䜓を返し" , "



。



そしお最埌に、最もトリッキヌなケヌス-目的の郚分文字列が巊右のサブツリヌの䞀郚に重なりたす。

この堎合、巊のサブツリヌにのみ入るピヌスを遞択し、次に右のサブツリヌに入るピヌスを遞択しお、それらをマヌゞする必芁がありたす。 2本のロヌプを結合する方法はすでに知っおいたす。

垌望するピヌスのむンデックスを決定するこずはたったく難しくありたせん。 巊サブツリヌの再垰呌び出し

Substring( start : start, len : T.Left.Size - start)





右の堎合

Substring( start : 0, len : len - (T.Left.Size - start))



。

繰り返したすが、右のサブツリヌにれロをstart



匕数ずしお枡す必芁がありたした。そのサブツリヌの関数は独立しお動䜜するためです。

これらのむンデックスが明らかでない堎合は、図を芋おください。


最終的に、再垰呌び出しは、サブストリング芁求がすでにセグメントに沿っお通垞の線圢方法で行われおいるリヌフに到達したす。 これにより、最倧のパフォヌマンスが保蚌されたす。 操䜜の合蚈耇雑床はOlog Nです。



その他


このようなデヌタ構造は、文字列の実装だけでなく䜿甚できるず蚀う必芁はないず思いたす。 芁玠の巚倧なシヌケンスは、同様の圢匏で衚すこずができたす。基瀎ずなるリヌフセグメントに最適な長さを遞択するだけで十分です。 -巚倧な長さの䞍倉のシヌケンスを操䜜するための䟿利なデヌタ構造を取埗したす。 確かに、これたでのずころ、そのような移行の説埗力のある議論ずしお圹立぀十分な操䜜が実蚌されおいたせん。 䜕も、それは修正可胜です:)



構造の遞択に関しお。 デヌタをリヌフに保存する任意の自己バランス型バむナリツリヌたずえば2-3ツリヌたたはB ツリヌを遞択できたす。 䞻にセットの実装甚に䜜成された倚くの怜玢ツリヌは、 赀黒ツリヌやデカルトツリヌなど、各頂点にデヌタを保存したす。 それらに文字列行を実装するこずは実甚的ではありたせん。これにより、操䜜䞭に倧量のメモリ割り圓おが発生し、コヌドがやや耇雑になりたすが、この蚘事の䞻なタスクであるモノむドを持぀ツリヌのパラメヌタヌ化は、第1および第2のツリヌの䞡方に簡単に適しおいたす したがっお、ストヌリヌの過皋で、プレれンテヌションを容易にし、さたざたなバランスの取れたツリヌの実珟の詳现で混乱しないように、時にはデカルトツリヌに関する蚘事のテキストを参照し、時にはフィンガヌツリヌを参照したす。これは完党に䞍芁です。 読者があらゆるアプロヌチを完党に理解し、受け入れるこずを願っおいたす。




パラメヌタ化、たたはツリヌの枬定方法





デカルトツリヌの䟋を䜿甚しお、サブセグメントで耇数のク゚リを䜜成した方法を思い出しおください。 手短に蚀えば、この抂念の本質を思い出させおください。ツリヌの各頂点に特定の泚釈が保存されたした。その頂点にルヌトを持぀サブツリヌに察応するサブセグメントの芁求倀に等しいパラメヌタヌです。 たずえば、サブツリヌ芁玠の合蚈、サブツリヌ芁玠の最倧倀、サブセグメント䞊のブヌルフラグの有無などです。 ナヌザヌがサブセグメントでリク゚ストを行いたい堎合、䞀郚のサブツリヌでは回答がすでに頂点にキャッシュされおおり、それらを結合するためにのみ残っおいるため、探しおいるすべおの頂点に察しおONずしお毎回再蚈算する必芁はありたせんでした



デカルトツリヌでは、各頂点で正矩を埩元するためのすべおの「ブラックワヌク」はSplit関数によっお行われたした。必芁なサブセグメントをツリヌから切り取り、ルヌトの蚈算倀をリク゚ストぞの応答ずしお取埗するだけで枈みたした。 しかし、別の方法で行うこずもできたす。 ロヌプで郚分文字列を取埗するアルゎリズムを芚えおいたすか 圌は䞊から䞋に再垰的に䞋降し、目的の郚分文字列の巊右の境界をロヌカラむズし、途䞭で芋぀けたものをすべおマヌゞしたした。 このアプロヌチはここで完党に適甚できたす。



頂点にある泚釈付きの暗黙的なデカルトツリヌ-サブツリヌの合蚈-を再床怜蚎し、サブセグメントの合蚈をク゚リしようずしたす[4; 8]



[4; 8]



。



結果を0に初期化したす。

反埩1では、巊のサブツリヌ[0; 9]。 結果は0のたたです。

反埩2では、右のサブツリヌ[5; 9]。 結果は、ルヌトの倀-42で増加したす。

反埩3では、右のサブツリヌ[8; 9]。 結果は、巊のサブツリヌの合蚈[5; 6]にルヌトの倀を加えお、42 + 23 + 3 = 68になりたす。

反埩4では、巊のサブツリヌ[8; 8]。 結果は68のたたです。

反埩5では、結果に29のルヌトの倀を远加し、合蚈97を取埗したす。これが問題の答えです。



スキヌムは、各頂点でよく知られおいるケヌス分析に基づいお非垞に単玔です。芁求されたセグメントは、巊息子、右息子、および自分に察応するセグメントずどのように察応したすか これに基づいお、巊右のサブセグメントの倀を蚈算しお合蚈する1぀たたは2぀の再垰呌び出しを行いたす䞊蚘の䟋では、2぀の再垰呌び出しは必芁ありたせんでした。 堎合の分析で今だけはただルヌトに保存されたデヌタを考慮する必芁がありたす。



葉の䞊郚ず䞊郚にサブセグメントの合蚈に察応する泚釈が栌玍されおいるロヌプを簡単に想像できたす。 次に、サブセグメントの金額のリク゚ストは、前の段萜からサブストリングを取埗するアルゎリズムず構造が同じで、この金額を环積し、再垰から戻る-結果に答えを远加し、より高い倀を枡したす。 スキヌムの単玔さは疑いの䜙地がありたせん。なぜ正しい答えが垞に埗られるのかを理解したいだけです。



これを理解するのも簡単です。 実際、単玔にサブセグメントのすべおのセルを盎線的にたどったのず同じ合蚈を実行したす。ここでは、aセルのブロック党䜓のみを芁玄したす。 b必ずしも巊から右の順序ではありたせん。 実際、次のようなプロセスを想像できたす。

行パスC l + C l + 1 + ... + C r 

ツリヌ芁求C l +C l + 1 + ... + C i +C i + 1 + ... + C j +C j + 1 + ... + C r-1 + ... + C r 

実際には、単に他の順序でブラケットを配眮したすが、これは結果を倉曎するものではありたせん。「+」は連想操䜜であるためです。 ああ、私は最初の段萜からおなじみの蚀葉に出䌚った:)もっず䞀般的な抂念がここで぀぀かれおいるようだ...



枬定する


ツリヌに含たれる䞀連の芁玠を特城付ける関数を、ツリヌの尺床ず呌びたす。 通垞、ツリヌメゞャヌは、埌でク゚リを実行する操䜜です。芁玠の合蚈、芁玠の最倧倀、芁玠䞊のフラグの存圚など、すでに䟋を瀺しおいたす。たずえば、平方和や文字の頻床のヒストグラムなど、より耇雑な枬定倀を想像できたす。



すでに知られおいる手法を䜿甚しお、どのメゞャヌも各サブツリヌのロヌプの䞊郚にキャッシュできたす。次に、枬定関数が結合的である堎合、䞊蚘のアルゎリズムによる任意のサブセグメントの枬定芁求を察数時間で簡単に実行できたす。このプロパティに、ツリヌの個々の芁玠のメゞャヌを決定する機胜の完党に論理的な芁件を远加したす。



普遍的なデヌタ構造、぀たりロヌプを取埗したす。これにより、ロヌプの接着や切断埌など、サブセクションのメゞャヌの倀をすばやく照䌚できたす。ツリヌはそれ自䜓でバランスが取れおいるため、アクセス時間は察数のたたです芁玠を远加するず、新しいサブツリヌのキャッシュされたメゞャヌ倀が再蚈算され、未倉曎のサブツリヌは同じたたになりたす。 Oのすべおlog N。玠晎らしい。



さお、メゞャヌの定矩を少し絞りたしょう。ツリヌの各具䜓的な単䞀芁玠のみを枬定する方法を教えおください。今サブツリヌの枬定倀を取埗する方法はずおも簡単です。1぀の芁玠の枬定倀ず他の芁玠の枬定倀の組み合わせが、それらの2぀のセットの枬定倀を䞎えるように、2぀の枬定倀を互いに組み合わせるこずができれば十分です。同時に、この結合プロセスは連想的である必芁がありたす。そうしないず、ク゚リアルゎリズムが誀った答えを受け取りたす。これらの考慮事項により、自然な結論に至りたす。枬定倀は任意の関数であり、その結果はモノむドの芁玠です。



「最倧」メゞャヌは、モノむド<Numbers、max、-∞>の結果を持぀xの基本関数です。

「二乗和」メゞャヌは、モノむド<Numbers、+、0>の結果を持぀基本関数x 2です。

枬定「呚波数ヒストグラム」-基本関数「単䞀の指定されたシンボルに察しお100」結果はモノむド<ヒストグラム、文字数を考慮したヒストグラム、空のヒストグラムを組み合わせたもの>になりたす。読者は、挔習ずしお、頻床ヒストグラムを結合する完党に関連する操䜜を怜蚎する必芁がありたす。



ここで達成したこずをコヌドで説明したす。これからは、Cでの同じアむデアの実装が非垞にugく倚音節に芋えるため、Haskellに完党に切り替えるずよいでしょう。たずえば、ツリヌは2぀ではなく3぀の兞型的なパラメヌタヌでパラメヌタヌ化する必芁がありたす

バランスを取るこずなく、実際に远加/接着/切断するこずなく、単玔なバむナリツリヌの実装を提䟛したす。これらの操䜜がどのように実装されるかは、特定のタむプのバランスのずれたツリヌごずに固有であり、別の蚘事が必芁になりたすが、これは私の目暙ではありたせん。読者は簡単にクラスの代わりに想像するこずができたすTree



䟋えば、FingerTree



。たたは、ImplicitTreap



「正矩の回埩」の察応する機胜が曞き盎され、デヌタがツリヌの頂点にも保存され、ツリヌの頂点の子孫もヌルになる可胜性があるこずを考慮した、やや耇雑なもの。

 //  ,   . public interface IMeasured<V> { V Measure { get; } } //  :      public class IdentityMeasure<T> : IMeasured<T> { public readonly T Data; public IdentityMeasure(T data) { Data = data; } public T Measure { get { return Data; } } } // T -      // V -      // M - ,         public class Tree<T, M, V> : IMeasured<V> where M: IMonoid<V>, new() where T: IMeasured<V> { public readonly T Data; //    public readonly Tree<T, M, V> Left; public readonly Tree<T, M, V> Right; private readonly V _measure; public V Measure { get { return _measure; } } public Tree(T data) //   { Left = Right = null; Data = data; _measure = data.Measure; } public Tree(Tree<T, M, V> left, Tree<T, M, V> right) //   { Left = left; Right = right; Data = default(T); _measure = Singleton<M>.Instance.Append(left.Measure, right.Measure); } } //  ,      public class SumTree : Tree<IdentityMeasure<int>, AddMonoid, int> { public SumTree(int data) //   : base(new IdentityMeasure<int>(data)) {} public SumTree(SumTree left, SumTree right) //   : base(left, right) {} } //  ,      public class PriorityTree : Tree<IdentityMeasure<double>, MaxMonoid, double> { public PriorityTree(double data) //   : base(new IdentityMeasure<double>(data)) {} public PriorityTree(PriorityTree left, PriorityTree right) //   : base(left, right) {} }
      
      







このセクションのすべおの努力の集倧成は、サブトリム枬定を芁求するための䞀般化された方法になりたす。

 //  . //      : Size = 1 + left.Size + right.Size; public readonly int Size = 1; public V MeasureOn(int start, int length) { if (start == 0 && length == Left.Size) return Left.Measure; if (start == Left.Size && length == Right.Size) return Right.Measure; if (start + length <= Left.Size) return Left.MeasureOn(start, length); if (start >= Left.Size) return Right.MeasureOn(start - Left.Size, length); var monoidV = Singleton<M>.Instance; var leftValue = Left.MeasureOn(start, Left.Size - start); var rightValue = Right.MeasureOn(0, length - (Left.Size - start)); return monoidV.Append(leftValue, rightValue); }
      
      







新しいステヌゞ述語



モノむドによっおパラメヌタヌ化されたロヌプに察しお実行できる操䜜のクラスをさらに拡匵できたす。サブセグメントに関するさたざたな察策の芁求を満たす方法をすでに知っおいたす。しかし、人生ではしばしば、特定の意味を知るこずだけでなく、その創造に「䞻に」関䞎する芁玠も必芁です。



たずえば、メゞャヌがセグメント内の芁玠の最倧倀である堎合、このアカりントがこの最倧倀に達する特定の芁玠を知るず䟿利です。叀い良奜なむンデックスアクセスは、同じ操䜜にも適甚されたす。思い出すように、これらの操䜜はすべお非垞によく䌌たアルゎリズムで蚘述されおいたす。これは、ツリヌの頂点から目的のリヌフに到達するたで、頂点から盎線に䞋降したす。したがっお、このようなすべおの操䜜を䞀般化する非垞に簡単な方法がありたす。



いく぀かの述語 pを考えたす、぀たり、1぀の任意の匕数のブヌル関数。

我々は、オブゞェクトの配列を有するたしょう1 ... Nのを。オブゞェクトは、ある皮のモノむドの芁玠です。たずえば、行にしたす。シヌケンスのプレフィックス合蚈を順次蚈算したす。これは、この新しいシヌケンスです1 1 ⊗ 2 1 ⊗ 2 ⊗ 3











...

1 ⊗ 2 ⊗ 3 ⊗···⊗ Nのずころ「⊗」、我々は、合意した-モノむドの操䜜を。文字列を䜿甚した䟋では、連結になりたす。ここで、これらのすべおのプレフィックスの合蚈に぀いお述語の倀を蚈算したす。ブヌル倀のシヌケンスを取埗したす。そしお最埌に、接頭蟞の和で垞にFalseである堎合、述語モノトヌンを呌び出し、ある時点でFalseをTrueに倉曎し、その埌シヌケンスの最埌たでTrueのたたになりたす。簡単に蚀えば、Falseを0に、Trueを1に眮き換えるず、述郚の結果のシヌケンスは枛少しないはずです。













モノむド文字列の図でこのプロパティを瀺したす。たしょうPS= { sが含た""



ストリングずしお}。

ロヌプの䞊郚には、メゞャヌ倀、぀たりサブツリヌラむンの連結がキャッシュされおいたす。



アルゎリズムは垞に2぀のプレフィックスをサポヌトしおいたす。1぀は珟圚の巊の息子を考慮せず、もう1぀はそれを含めたす。これらのプレフィックスの述語の倀に応じお、どのサブツリヌ内で「ゞャンプ」が発生したかを垞に正確に刀断できたす。

たずえば、ロヌプのルヌトにいるずき、アルゎリズムはp" "



= Falseを怜出したした
。これは、ゞャンプが右のサブツリヌで発生したこずを意味したす。しかし、次の反埩では、巊接頭蟞pの倀" , "



= True
であるため、巊のサブツリヌに移動する必芁がありたす。



降䞋䞭、プレフィックスの正しい倀を垞に維持し、右サブツリヌぞの降䞋の堎合、珟圚の巊の息子の尺床でそれを接着する必芁がありたす。



最終的に、察数のステップで、ゞャンプが発生したシヌトに到達したす。リヌフセグメントの内郚では、別の方法で正確なゞャンプ䜍眮を探す必芁がありたす。ほずんどの堎合、順次チェックが必芁です。ただし、これはささいなこずではないかもしれたせん。「特定の郚分文字列を含む」述語の代わりに、「特定の正芏衚珟を満たす」述語を想像しおください。たた、単調ですが、蚈算には倚少の劎力が必芁です。



たずえば、「平方の合蚈」ずいう圢匏ず「256を超える」述語のメゞャヌの堎合、ゞャンプの正確な䜍眮を決定するために、シヌト内のセグメントから特定の各数倀の平方を個別に蚈算する必芁もありたす。



ずころで。単語を含むセグメントではなく、シヌト内の文字を別々に保存する堎合、このアルゎリズムに基づいお、分割操䜜を決定できたす。単調な述語に埓っおツリヌを2぀にカットしたす。巊偎の結果では、述語プロパティはただ満たされおおらず、右偎では、すでに満たされおいたす。正確な分割アルゎリズムの実装は、挔習ずしお読者に明確な良心を委ねるこずができたす:)

ずころで、次の段萜の1぀では、それはただ有甚です。

, . , . .




しかし、たずえば、むンデックスiを持぀芁玠ぞのアクセスは、単調な述語「prefix length> i」を䜿甚したツリヌ内の単なる怜玢であるこずは明らかです。プレフィックスの長さは通垞の尺床であり、頂点にサブツリヌのサむズを栌玍する際の尺床ずしお䜿甚したした。この枬定では、基本関数は単䜍単䜍であり、倀はモノむド<Numbers、+、0>にありたす。䜍眮番号i-これは、シヌケンスプレフィックスの長さがiを超え始める䜍眮です。



遞択された䟋





そこで、モノむドを䜿ったロヌプのパラメヌタヌ化などの抂念がもたらす䞻な利点をすべお調べたした。「枬定可胜な」倀の任意のシヌケンスを取埗し、結果のシヌケンスのサブセグメントに察しお、メゞャヌの倀を認識しお、それらを次々に結合できたす。興味がある堎合は、単調な述語に埓っお結果のロヌプを切断するこずで、達成の正確な䜍眮を芋぀けるこずができたす。そしお、これらすべおを察数時間で行い、可胜性の範囲を無限にしたす。この無制限のスコヌプを今すぐ実行しお、3぀のかなり暙準的ではない、非垞に重芁で興味深いモノむドを玹介したす。



䟋1統蚈




今回は、退屈な数字、文字列、ブヌルよりも退屈なものを操䜜しおいたす。私たちの现心の泚意の察象は...サンプルです。



サンプル、぀たり特定の母集団からの有限なランダム倀のセットが枬定可胜です。誰もがサンプルの䞻な特城を知っおいたす

N-サンプルサむズ。

Mはサンプルの平均倀です。

Vは暙本の分散、぀たり、平均暙本からの偏差の二乗の平均倀です。スケヌリングされおいない分散、぀たり、単に平均からの偏差の二乗の合蚈

を考慮したす。必芁であれば、これは単玔に数割る、基本かもしれそれから抜け出すNのを。






䞋の段萜で、サンプルは「枬定可胜」であるず述べたした。はい、この蚀葉を誀っお䜿甚したこずはありたせんでした:)サンプルのこれら3぀の基本的な特性のセットが、その尺床ずしお圹立ちたす。

ストップ-ストップ-ストップ、あなたは蚀う、3぀の疎結合された数の同じセットは䜕ですか-モノむドの芁玠ですかそれはどんなモノむドですかどういうわけかサンプルを結合する必芁がありたす、それが刀明したすしかし、どうですか



これはすべお矎しく行われたす。同じ母集団からの2぀のサンプルAずBがあるずしたす。これらのサンプルをマヌゞしお、共同サンプルXを䜜成したす。このサむズは、元のサンプルのサむズの合蚈です。その埌、1979幎にトニヌチャンが瀺したように、新しいサンプルの平均およびスケヌルなしの分散は、次の匏を䜿甚しお蚈算できたす。









明らかに、サンプルをどの順序で混合するかは重芁ではありたせん。最終サンプルの特性は同じです。したがっお、サンプルのマヌゞは結合的です。

空のサンプルの特性が䜕であるかを刀断するのは、圢匏的なたたです。そのサむズは明らかに0であり、盞加性による平均も0になりたすが、分散を十分に決定するこずはできたせん。ただし、必芁はありたせん。ツリヌでは、空のサンプルの分散にたったく觊れたせん。



統蚈的特城のモノむドずそれに続くすべおの定矩をpastie.orgに定矩する必芁がありたした。これは、蚘事のサむズに察するHabrahabrの制限がやや緊匵し始めるためです:)



サむズKの「りィンドり」が移動するランダム倉数のストリヌム、぀たり 最埌のK個の量の分散ず期埅倀を垞に知る必芁がありたす。ツリヌが䜜成され、芁玠がキュヌから順次削陀されお远加され、必芁な蚈算倀は垞にツリヌのルヌトにありたす。矎人



䟋2画像のアルファ合成




2぀の半透明の画像がありたすアルファチャネル付き。アルファ合成ずしお知られおいる2぀の画像のオヌバヌレむ挔算子を定矩したす。Photoshopで半透明の画像を䜿甚したこずがある人は誰でも、その動䜜に粟通しおいたす。画像の各ピクセルには、カラヌCずアルファチャネルαの 2぀のパラメヌタヌが定矩されおいたす。これらの倀を蚈算するための匏を完党に明確に定矩するず、重ね合わせ挔算子が定矩されたす。したがっお、次の事実は数孊的に簡単に導き出せるこずがわかりたす。






これらの事実ず特定の公匏の蚌明に぀いおは、察応するりィキペディアの蚘事を参照しおください。



したがっお、アルファ合成の動䜜の半透明の画像はモノむドを圢成したす。これにより、適切なツリヌを䜿甚しお、互いに重ね合わせる必芁がある巚倧な画像のセットを凊理する機䌚が䞎えられたす。



䟋3正芏衚珟


残念ながら、Habrahabrによっお蚘事に課されたボリュヌムは、私がそれを知的に仕䞊げるこずができず、3番目の矎しいモノむド、すなわち正芏衚珟を認識するための有限オヌトマトンの遷移関数のモノむドを詳现に説明するこずはできたせん。これをロヌプで䜿甚するず、むンクリメンタルレクサヌを䜜成できたす。これは、行をすばやく倉曎し、指定された正芏衚珟が前の行ず䞀臎する堎合にい぀でも即座に答えを出すこずができる構造です。詳现に぀いおは、Dan Piponi による元の蚘事の翻蚳ず、より詳现な蚘事である Eugene Kirpichevの実装を参照しおください。播皮画像









それたでの間、ご枅聎ありがずうございたした。



All Articles