گره سلطه گر

بندانگشتی|در این گراف جهت دار با توجه به شکل می‌توان دید که گره ۱ بر تمام گره‌ها غلبه می‌کند.  گره ۲ بر تمام گره ها به جز گره ۱ غلبه می‌کند و دیگر گره‌ها در گراف فقط بر خود غلبه می‌کنند. همچنین گره ۱برای گره ۲ یک گره سلطه گر آنی محسوب می‌شود و گره ۲ نیز برای گره های ۳، ۴، ۵ و ۶ گره سلطه گر آنی بوده.
در گراف های جهت دار، زمانی می‌گوییم گره w بر گره v غلبه می‌کند که  به ازای هر گره n همه مسیر ها از n به v، از گره w عبور کند. در نتیجه می‌توان گفت هر گره بر خودش غلبه می‌کند. با توجه به تعریف می‌توان برای هر گره مجموعه‌ای از گره های سلطه گر در نظر گرفت که بر این گره غلبه می‌کنند. همچنین می‌توان برای هر گراف یک درخت سلطه گر تعریف کرد که به ازای هر گره در گراف، اجداد این گره در  درخت، گره های سلطه گر بر این گره در گراف هستند.  
* گره v بر گره w اکیداً غلبه می‌کند زمانی که گره v بر گره w غلبه کرده و v \neq w باشد.
* گره‌های سلطه گر آنی گره v به مجموعه گره‌هایی می گویند که فقط بر گره v به صورت اکید غلبه کرده و بر هیچ گره دیگری اکیداً غلبه نکند.
* گره‌های سلطه گر مرزی گره v به مجموعه گره‌هایی می‌گویند که  گره v  بر والدهای مستقیم آنها غلبه کرده ولی به صورت اکید بر  آن گره‌ها غلبه نکند.

بندانگشتی|درخت سلطه‌گر حاصل از گراف موجود در تصویر.
بنابر تعریف می‌توان برای سلطه گری اکید نتیجه گرفت که نزدیک گره سلطه گر اکید برای هر گره یکتا بوده و یک گره برای آن وجود دارد.

## تاریخچه و کاربرد
تعریف گره سلطه گر یا غالب برای اولین بار توسط ریس پروسر در مقاله‌ای  تحت عنوان کاربردهای ماتریس بولی برای  تحلیل نمودارهای جریان ارائه شد. او در این مقاله الگوریتمی برای پیدا کردن گره های سلطه گر ارائه نکرد و صرفاً آن را تعریف کرده. اولین الگوریتم برای این مساله ده سال بعد توسط ادوارد لوری و مدلاک ارائه شد. از کاربرد های آن می‌توان به زمینه های بهینه سازی برنامه، تولید کد، تست مدار اشاره کرد. همچنین در کامپایلر ها از اطلاعات حاصل از  سلطه گری گره‌ها استفاده زیادی می‌شود. برای مثال یک کاربرد آن در کامپایلر برای پیدا کردن حلقه ها در بهینه سازی کد به کمک بلوک های پایه است.

## الگوریتم پیدا کردن گره‌های سلطه گر
با توجه به تعریف برای هر گره n اگر \text{Dom}(n) برابر با مجموعه گره‌های سلطه گر  بر گره n در نظر بگیریم آنگاه رابطه زیر را خواهیم داشت.

\text{Dom}(n) = (\bigcap_{p\in preds(n)} \text{Dom}(p))\ \cup\ \{n\}در اینجا preds(n) برابر است با مجموعه تمام گره‌هایی که وارد گره n می‌شوند یعنی یک یال از سمت آنها به n وجود دارد. همچنین برای گره شروع در گراف داریم

\text{Dom}(n_0) = \{n_0\}

با داشتن این اطلاعات برای پیدا کردن گره‌های سلطه گر هر گره در گراف می‌توان الگوریتم زیر را پیاده سازی کرد.
```python3
// n0 : start node
for n in graph - {n0}:
    Dom[n] = graph

changed = True
while changed:
    changed = False
    for n in graph:
        new = []
        for p in preds(n):
            new = intersection(new, Dom[p])
        new = new + [n]
        if new != dom[n]:
            dom[n] = new
            changed = True
```
این الگوریتم در زمان اجرای O(n^{2}) تمام مجموعه های سلطه گر را می‌یابد که می‌توان با استفاده از داده ساختار های خاص زمان اجرا را بهتر کرد. الگوریتم دیگری توسط رابرت تارجان و  توماس لینگوار ارائه شده که به وسیله الگوریتم جستجوی اول عمق (الگوریتم dfs) در زمان تقریباً خطی این کار را انجام می‌دهد.

## الگوریتم پیدا کردن گره‌های سلطه گر مرزی
با توجه به تعریف برای گره سلطه گر مرزی می‌توان رابطه های زیر را بدست آورد.

\text{DF}(v) = \text{SUCC}(DOM^{-1}(v))-\text{DOM!}^{-1}(v)

که در اینجا \text{DF}(v) همان مجموعه گره‌های سلطه گر مرزی v است و \text{DOM}^{-1}(v) برابر مجموعه گره‌هایی است که v بر آن‌ها غلبه می‌کند و  \text{DOM!}^{-1}(v) برابر است با \text{DOM!}^{-1}(v)-\{v\}. همچنین برای \text{SUCC}(S) که S یک مجموعه است داریم \text{SUCC}(S) = \bigcup_{s\in S} \text{SUCC}(s) که اینجا \text{SUCC} برای گره s برابر است مجموعه تمام گره هایی که از s به آنها در گراف جهت دار مسیر وجود دارد. با این رابطه ها می‌توان رابطه زیر را بدست آورد.

\text{DF}(v) = \text{DF}_{local}(v)\cup (\bigcup_{w \in Children(v)}\text{DF}_{up}(w))

که در اینجا Children(v) فرزندان v در درخت سلطه گر اند. \text{DF}_{local}(v) برابر است با تمام \text{SUCC}(v) که v بر آنها را به صورت اکید غلبه نمی‌کند. \text{DF}_{up}(w) زیر مجموعه‌ای از \text{DF}(w) است که v بر آنها به صورت اکید غلبه نمی‌کند. با توجه به این رابطه الگوریتم زیر بدست می‌آید.
```python3
def FindDF(v):
    DF[v] = []
    for w in children(v):
        FindDF(w)
        for u in DF[w]:
            if not strictly_dom(v,u):
                DF[v].append(u)
    for w in succ(v):
        if not strictly_dom(v,w):
                DF[v].append(w)
```


## منابع

رده:کامپایلرسازی
رده:نظریه گراف