<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-09-25T18:05:45+00:00</updated><id>https://program.sonsuz.us/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">2-SAT Problemlerini SCC ile Doğrusal Zamanda Çözmek</title><link href="https://program.sonsuz.us/posts/2-sat-problemlerini-scc-ile-dogrusal-zamanda-cozmek/" rel="alternate" type="text/html" title="2-SAT Problemlerini SCC ile Doğrusal Zamanda Çözmek" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/2-sat-problemlerini-scc-ile-dogrusal-zamanda-cozmek</id><content type="html" xml:base="https://program.sonsuz.us/posts/2-sat-problemlerini-scc-ile-dogrusal-zamanda-cozmek/"><![CDATA[<p>Bir festivalde her etkinlik için “yapılsın” veya “yapılmasın” kararı verdiğimizi düşünelim. Kurallar ise “Konser yapılacaksa güvenlik ekibi gelsin” ya da “Ya konser ya tiyatro seçilsin” biçiminde olsun. Binlerce ikili karar birbirine bağlandığında deneme-yanılma yaklaşımı hızla çöker. 2-SAT, tam da bu tür sistemlerin çözülebilirliğini yönlü grafikler ve güçlü bağlı bileşenler sayesinde zarifçe belirler.</p>

<p>``</p>

<h2 id="2-sat-nedir">2-SAT nedir?</h2>

<p>2-SAT formülleri, her parantezinde en fazla iki literal bulunan ve bağlaçlarla birleştirilen ifadelerdir:</p>

\[(x_1 \lor \neg x_2) \land (x_2 \lor x_3) \land (\neg x_1 \lor \neg x_3)\]

<p>Literal, bir değişkenin kendisi ($x$) veya değili ($\neg x$) olabilir. Genel bir madde $(a \lor b)$ biçimindedir. Bu ifade yalnızca $a$ ve $b$ birlikte yanlış olduğunda bozulur. Dolayısıyla şu iki zorunluluğu türetebiliriz:</p>

\[(a \lor b) \equiv (\neg a \Rightarrow b) \land (\neg b \Rightarrow a)\]

<p>Her zorunluluğu yönlü bir kenara dönüştürürsek <strong>implikasyon grafiği</strong> ortaya çıkar.</p>

<table>
  <thead>
    <tr>
      <th>Mantıksal kısıt</th>
      <th>Grafiğe eklenen kenarlar</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$a \lor b$</td>
      <td>$\neg a \to b$, $\neg b \to a$</td>
    </tr>
    <tr>
      <td>$a \Rightarrow b$</td>
      <td>$a \to b$, $\neg b \to \neg a$</td>
    </tr>
    <tr>
      <td>$a$ doğru olmalı</td>
      <td>$\neg a \to a$</td>
    </tr>
    <tr>
      <td>$a$ ve $b$ eşit</td>
      <td>$a \to b$, $b \to a$, $\neg a \to \neg b$, $\neg b \to \neg a$</td>
    </tr>
  </tbody>
</table>

<h2 id="scc-neden-çözümü-belirliyor">SCC neden çözümü belirliyor?</h2>

<p>Bir güçlü bağlı bileşende, her düğümden diğer bütün düğümlere ulaşılabilir. Eğer $x$ ile $\neg x$ aynı SCC içindeyse hem $x \Rightarrow \neg x$ hem de $\neg x \Rightarrow x$ geçerlidir. Hangi doğruluk değerini seçersek seçelim sistem tersini de zorlar; formül çözülemez.</p>

<p>Böylece temel ölçüt şudur:</p>

\[\text{Formül çözülebilir} \iff \forall x_i,\ SCC(x_i) \ne SCC(\neg x_i)\]

<p>Bu, yönlü döngülerin mantıksal çelişkiyi görünür hâle getirmesidir. SCC’ler Tarjan veya Kosaraju algoritmasıyla $O(V+E)$ zamanda bulunur. $n$ değişken ve $m$ madde için grafikte $2n$ düğüm, $2m$ kenar bulunduğundan toplam karmaşıklık $O(n+m)$ olur.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th style="text-align: right">Zaman</th>
      <th>Büyük girdilerde durum</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tüm atamaları denemek</td>
      <td style="text-align: right">$O(2^n)$</td>
      <td>Hızla kullanılamaz</td>
    </tr>
    <tr>
      <td>SCC tabanlı 2-SAT</td>
      <td style="text-align: right">$O(n+m)$</td>
      <td>Milyonlarca kısıta uygundur</td>
    </tr>
  </tbody>
</table>

<h2 id="kosaraju-ile-uygulama">Kosaraju ile uygulama</h2>

<p>Aşağıdaki C++ kodu, pozitif literali <code class="language-plaintext highlighter-rouge">2*x</code>, negatifini <code class="language-plaintext highlighter-rouge">2*x+1</code> ile temsil eder. <code class="language-plaintext highlighter-rouge">p^1</code> işlemi bir literalden karşıtına geçer. İlk DFS bitiş sırasını, ikinci DFS ise ters grafikte bileşenleri üretir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="k">struct</span> <span class="nc">TwoSAT</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">n</span><span class="p">;</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">g</span><span class="p">,</span> <span class="n">rg</span><span class="p">;</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">order</span><span class="p">,</span> <span class="n">comp</span><span class="p">,</span> <span class="n">used</span><span class="p">;</span>

    <span class="n">TwoSAT</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="o">:</span> <span class="n">n</span><span class="p">(</span><span class="n">n</span><span class="p">),</span> <span class="n">g</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">n</span><span class="p">),</span> <span class="n">rg</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">n</span><span class="p">),</span>
                    <span class="n">comp</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">n</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="n">used</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">n</span><span class="p">)</span> <span class="p">{}</span>

    <span class="c1">// (a OR b) maddesini implikasyon grafiğine ekler.</span>
    <span class="kt">void</span> <span class="nf">addClause</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">g</span><span class="p">[</span><span class="n">a</span> <span class="o">^</span> <span class="mi">1</span><span class="p">].</span><span class="n">push_back</span><span class="p">(</span><span class="n">b</span><span class="p">);</span>
        <span class="n">rg</span><span class="p">[</span><span class="n">b</span><span class="p">].</span><span class="n">push_back</span><span class="p">(</span><span class="n">a</span> <span class="o">^</span> <span class="mi">1</span><span class="p">);</span>
        <span class="n">g</span><span class="p">[</span><span class="n">b</span> <span class="o">^</span> <span class="mi">1</span><span class="p">].</span><span class="n">push_back</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
        <span class="n">rg</span><span class="p">[</span><span class="n">a</span><span class="p">].</span><span class="n">push_back</span><span class="p">(</span><span class="n">b</span> <span class="o">^</span> <span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kt">void</span> <span class="nf">dfs1</span><span class="p">(</span><span class="kt">int</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">used</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">u</span> <span class="o">:</span> <span class="n">g</span><span class="p">[</span><span class="n">v</span><span class="p">])</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">used</span><span class="p">[</span><span class="n">u</span><span class="p">])</span> <span class="n">dfs1</span><span class="p">(</span><span class="n">u</span><span class="p">);</span>
        <span class="n">order</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">v</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kt">void</span> <span class="nf">dfs2</span><span class="p">(</span><span class="kt">int</span> <span class="n">v</span><span class="p">,</span> <span class="kt">int</span> <span class="n">id</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">comp</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="n">id</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">u</span> <span class="o">:</span> <span class="n">rg</span><span class="p">[</span><span class="n">v</span><span class="p">])</span> <span class="k">if</span> <span class="p">(</span><span class="n">comp</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="n">dfs2</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">id</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kt">bool</span> <span class="nf">solve</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">&gt;&amp;</span> <span class="n">value</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">v</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">v</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="o">*</span><span class="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">v</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">used</span><span class="p">[</span><span class="n">v</span><span class="p">])</span> <span class="n">dfs1</span><span class="p">(</span><span class="n">v</span><span class="p">);</span>

        <span class="n">reverse</span><span class="p">(</span><span class="n">order</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">order</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
        <span class="kt">int</span> <span class="n">id</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">v</span> <span class="o">:</span> <span class="n">order</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">comp</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="n">dfs2</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">id</span><span class="o">++</span><span class="p">);</span>

        <span class="n">value</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">x</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">comp</span><span class="p">[</span><span class="mi">2</span><span class="o">*</span><span class="n">x</span><span class="p">]</span> <span class="o">==</span> <span class="n">comp</span><span class="p">[</span><span class="mi">2</span><span class="o">*</span><span class="n">x</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
            <span class="n">value</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">=</span> <span class="n">comp</span><span class="p">[</span><span class="mi">2</span><span class="o">*</span><span class="n">x</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">comp</span><span class="p">[</span><span class="mi">2</span><span class="o">*</span><span class="n">x</span><span class="o">+</span><span class="mi">1</span><span class="p">];</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">solve</code>, çelişki yoksa örnek bir doğruluk ataması da üretir. Bileşen numaralarına göre yapılan karşılaştırma, SCC’lerin yoğunlaştırılmış grafiğindeki ters topolojik sıradan yararlanır.</p>

<p>Sonuç olarak 2-SAT’ın gücü, mantığı kaba kuvvetle çözmek yerine onu erişilebilirlik problemine dönüştürmesinden gelir. Bir değişken kendi değiliyle aynı yönlü döngünün içine hapsolmuşsa çelişki kaçınılmazdır; aksi durumda bileşen sırası tutarlı bir atamayı doğrudan verir.</p>

<p><img src="/img/2-sat-problemlerini-73.svg" alt="2-sat-problemlerini-73" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="2-sat" /><category term="graf teorisi" /><category term="güçlü bağlı bileşenler" /><category term="algoritma" /><category term="kosaraju" /><category term="mantıksal kısıtlamalar" /><summary type="html"><![CDATA[Bir festivalde her etkinlik için “yapılsın” veya “yapılmasın” kararı verdiğimizi düşünelim. Kurallar ise “Konser yapılacaksa güvenlik ekibi gelsin” ya da “Ya konser ya tiyatro seçilsin” biçiminde olsun. Binlerce ikili karar birbirine bağlandığında deneme-yanılma yaklaşımı hızla çöker. 2-SAT, tam da bu tür sistemlerin çözülebilirliğini yönlü grafikler ve güçlü bağlı bileşenler sayesinde zarifçe belirler.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/2-sat-problemlerini-73.png" /><media:content medium="image" url="https://program.sonsuz.us/img/2-sat-problemlerini-73.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Fenwick Ağacı ile Çok Boyutlu Aralık Sorgularında Bellek Tasarrufu</title><link href="https://program.sonsuz.us/posts/fenwick-agaci-ile-cok-boyutlu-aralik-sorgularinda-bellek-tasarrufu/" rel="alternate" type="text/html" title="Fenwick Ağacı ile Çok Boyutlu Aralık Sorgularında Bellek Tasarrufu" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/fenwick-agaci-ile-cok-boyutlu-aralik-sorgularinda-bellek-tasarrufu</id><content type="html" xml:base="https://program.sonsuz.us/posts/fenwick-agaci-ile-cok-boyutlu-aralik-sorgularinda-bellek-tasarrufu/"><![CDATA[<p>Bir oyun haritasındaki kaynak miktarlarını, elektronik tablodaki hücre değerlerini veya koordinat düzlemindeki hareketli puanları sürekli güncellediğimizi düşünelim. Her değişiklikten sonra dikdörtgen bir bölgenin toplamını hesaplamak, naif yöntemle pahalıdır. Fenwick Ağacı ya da kısa adıyla <strong>BIT (Binary Indexed Tree)</strong>, segment ağacına göre daha az kod ve yardımcı bellek kullanarak bu işi logaritmik sürede yapar.</p>

<p>``</p>

<h2 id="fenwick-ağacının-temel-fikri">Fenwick Ağacının temel fikri</h2>

<p>Tek boyutlu BIT, her indeksin belirli uzunluktaki bir aralığın toplamını saklamasına dayanır. Bir indeksin sorumlu olduğu aralık, ikili gösterimindeki en düşük anlamlı bit ile belirlenir:</p>

\[lowbit(x)=x\ \&amp;\ (-x)\]

<p>Örneğin $12=(1100)_2$ için $lowbit(12)=4$ olur. Güncelleme sırasında indeksleri $lowbit(i)$ kadar artırır, önek toplamında ise aynı miktarı çıkarırız. Böylece her işlem en fazla $O(\log n)$ düğüme dokunur.</p>

<p>İki boyutta aynı düşünceyi satır ve sütun eksenlerine ayrı ayrı uygularız. $(x,y)$ noktasına eklenen değer, iki iç içe Fenwick yürüyüşüyle ilgili hücrelere taşınır. Bir dikdörtgen toplamı ise dahil etme–hariç tutma ilkesiyle bulunur:</p>

\[R(x_1,y_1,x_2,y_2)=P(x_2,y_2)-P(x_1-1,y_2)-P(x_2,y_1-1)+P(x_1-1,y_1-1)\]

<p>Burada $P(x,y)$, $(1,1)$ ile $(x,y)$ arasındaki önek toplamıdır.</p>

<h2 id="segment-ağacı-mı-fenwick-mi">Segment ağacı mı, Fenwick mi?</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th style="text-align: right">2B Fenwick Ağacı</th>
      <th style="text-align: right">2B Segment Ağacı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Nokta güncelleme</td>
      <td style="text-align: right">$O(\log n\log m)$</td>
      <td style="text-align: right">$O(\log n\log m)$</td>
    </tr>
    <tr>
      <td>Dikdörtgen toplamı</td>
      <td style="text-align: right">$O(\log n\log m)$</td>
      <td style="text-align: right">$O(\log n\log m)$</td>
    </tr>
    <tr>
      <td>Tipik yardımcı bellek</td>
      <td style="text-align: right">Yaklaşık $nm$</td>
      <td style="text-align: right">Yaklaşık $4n\cdot4m$</td>
    </tr>
    <tr>
      <td>Uygulama karmaşıklığı</td>
      <td style="text-align: right">Düşük</td>
      <td style="text-align: right">Yüksek</td>
    </tr>
    <tr>
      <td>Min/maks gibi işlemler</td>
      <td style="text-align: right">Sınırlı</td>
      <td style="text-align: right">Daha esnek</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/fenwick-agaci-ile-35.svg" alt="fenwick-agaci-ile-35" /></p>

<p>BIT’in önemli sınırlaması, işlemin tersinin bulunabilmesidir. Toplamada çıkarma sayesinde iki önekten aralık üretilebilir. Ancak genel minimum sorgusunda “önek minimumlarını çıkarma” diye bir işlem yoktur. Bu durumda segment ağacı daha doğru seçimdir.</p>

<h2 id="bellek-dostu-2b-uygulama">Bellek dostu 2B uygulama</h2>

<p>Aşağıdaki C++ sınıfı matrisi satır satır tek bir <code class="language-plaintext highlighter-rouge">vector</code> içinde tutar. Ayrı ayrı vektörler oluşturmadığı için tahsis maliyetini azaltır ve önbellek yerelliğini iyileştirir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="k">class</span> <span class="nc">Fenwick2D</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="p">;</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;</span> <span class="n">bit</span><span class="p">;</span>

    <span class="kt">long</span> <span class="kt">long</span><span class="o">&amp;</span> <span class="n">at</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">bit</span><span class="p">[</span><span class="n">x</span> <span class="o">*</span> <span class="p">(</span><span class="n">m</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">y</span><span class="p">];</span>
    <span class="p">}</span>

<span class="k">public</span><span class="o">:</span>
    <span class="n">Fenwick2D</span><span class="p">(</span><span class="kt">int</span> <span class="n">rows</span><span class="p">,</span> <span class="kt">int</span> <span class="n">cols</span><span class="p">)</span>
        <span class="o">:</span> <span class="n">n</span><span class="p">(</span><span class="n">rows</span><span class="p">),</span> <span class="n">m</span><span class="p">(</span><span class="n">cols</span><span class="p">),</span> <span class="n">bit</span><span class="p">((</span><span class="n">rows</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">cols</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{}</span>

    <span class="c1">// (x, y) noktasına delta ekler.</span>
    <span class="kt">void</span> <span class="nf">add</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">,</span> <span class="kt">long</span> <span class="kt">long</span> <span class="n">delta</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">&amp;</span> <span class="o">-</span><span class="n">i</span><span class="p">)</span>
            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="n">m</span><span class="p">;</span> <span class="n">j</span> <span class="o">+=</span> <span class="n">j</span> <span class="o">&amp;</span> <span class="o">-</span><span class="n">j</span><span class="p">)</span>
                <span class="n">at</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span> <span class="o">+=</span> <span class="n">delta</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// (1,1) ile (x,y) arasındaki toplamı döndürür.</span>
    <span class="kt">long</span> <span class="kt">long</span> <span class="nf">prefix</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">long</span> <span class="kt">long</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">-=</span> <span class="n">i</span> <span class="o">&amp;</span> <span class="o">-</span><span class="n">i</span><span class="p">)</span>
            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">-=</span> <span class="n">j</span> <span class="o">&amp;</span> <span class="o">-</span><span class="n">j</span><span class="p">)</span>
                <span class="n">result</span> <span class="o">+=</span> <span class="n">at</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">);</span>
        <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">long</span> <span class="kt">long</span> <span class="nf">rectangle</span><span class="p">(</span><span class="kt">int</span> <span class="n">x1</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y1</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x2</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y2</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">prefix</span><span class="p">(</span><span class="n">x2</span><span class="p">,</span> <span class="n">y2</span><span class="p">)</span> <span class="o">-</span> <span class="n">prefix</span><span class="p">(</span><span class="n">x1</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y2</span><span class="p">)</span>
             <span class="o">-</span> <span class="n">prefix</span><span class="p">(</span><span class="n">x2</span><span class="p">,</span> <span class="n">y1</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">prefix</span><span class="p">(</span><span class="n">x1</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y1</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>İndekslerin <strong>1’den başlaması</strong> önemlidir; sıfır için <code class="language-plaintext highlighter-rouge">lowbit(0)</code> sıfırdır ve güncelleme döngüsü ilerlemez.</p>

<h2 id="boyutlar-devasa-olduğunda">Boyutlar devasa olduğunda</h2>

<p>Koordinatlar milyarlara ulaşıyor fakat yalnızca birkaç bin nokta kullanılıyorsa tam matris ayırmak anlamsızdır. Güncelleme ve sorgulardaki koordinatları sıralayıp benzersizleştirerek <strong>koordinat sıkıştırma</strong> uygulanabilir. Her gerçek koordinat, sıralamadaki 1 tabanlı sırasına dönüştürülür.</p>

<p>$d$ boyutta güncelleme ve sorgu maliyeti yaklaşık $O(\log^d n)$ olur. Buna karşılık yoğun depolama $O(n^d)$ büyüdüğünden, pratikte üç ve üzeri boyutlarda yalnızca erişilen Fenwick hücrelerini karma tablo veya sıkıştırılmış iç vektörlerle saklamak gerekir. Kısacası toplam ve frekans sorgularında BIT, küçük kodu ve düşük sabit maliyetiyle güçlüdür; karmaşık birleştirme işlemlerinde ise segment ağacı hâlâ sahnededir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="fenwick ağacı" /><category term="bit" /><category term="veri yapıları" /><category term="algoritma" /><category term="aralık sorguları" /><category term="bellek optimizasyonu" /><category term="cpp" /><summary type="html"><![CDATA[Bir oyun haritasındaki kaynak miktarlarını, elektronik tablodaki hücre değerlerini veya koordinat düzlemindeki hareketli puanları sürekli güncellediğimizi düşünelim. Her değişiklikten sonra dikdörtgen bir bölgenin toplamını hesaplamak, naif yöntemle pahalıdır. Fenwick Ağacı ya da kısa adıyla BIT (Binary Indexed Tree), segment ağacına göre daha az kod ve yardımcı bellek kullanarak bu işi logaritmik sürede yapar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/fenwick-agaci-ile-35.png" /><media:content medium="image" url="https://program.sonsuz.us/img/fenwick-agaci-ile-35.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">FFT ile Dev Sayıları O(N log N) Sürede Çarpmak</title><link href="https://program.sonsuz.us/posts/fft-ile-dev-sayilari-on-log-n-surede-carpmak/" rel="alternate" type="text/html" title="FFT ile Dev Sayıları O(N log N) Sürede Çarpmak" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/fft-ile-dev-sayilari-on-log-n-surede-carpmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/fft-ile-dev-sayilari-on-log-n-surede-carpmak/"><![CDATA[<p>İlkokulda öğrendiğimiz uzun çarpma yöntemi küçük sayılarda harikadır; ancak milyonlarca basamak söz konusu olduğunda işler dramatik biçimde yavaşlar. Neyse ki sinyal işlemenin yıldızı Hızlı Fourier Dönüşümü, yani FFT, basamakları birer polinom katsayısı gibi ele alarak çarpma işlemini yaklaşık $O(N \log N)$ sürede gerçekleştirebilir.</p>

<p>``</p>

<h2 id="uzun-çarpma-neden-yavaş">Uzun çarpma neden yavaş?</h2>

<p>İki sayının da $N$ basamaklı olduğunu düşünelim. Geleneksel yöntemde birinci sayının her basamağı, ikinci sayının her basamağıyla çarpılır. Dolayısıyla yaklaşık $N^2$ işlem gerekir:</p>

\[T(N)=O(N^2)\]

<p>Basamak sayısı iki katına çıktığında çalışma miktarı yaklaşık dört katına çıkar. FFT tabanlı yaklaşımda ise büyüme çok daha sakindir:</p>

\[T(N)=O(N\log N)\]

<table>
  <thead>
    <tr>
      <th>Yöntem</th>
      <th style="text-align: right">Zaman karmaşıklığı</th>
      <th>Temel fikir</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Uzun çarpma</td>
      <td style="text-align: right">$O(N^2)$</td>
      <td>Tüm basamak çiftlerini çarp</td>
    </tr>
    <tr>
      <td>Karatsuba</td>
      <td style="text-align: right">$O(N^{1.585})$</td>
      <td>Çarpımları parçalayarak azalt</td>
    </tr>
    <tr>
      <td>FFT</td>
      <td style="text-align: right">$O(N\log N)$</td>
      <td>Konvolüsyonu frekans uzayında hesapla</td>
    </tr>
  </tbody>
</table>

<h2 id="sayıları-polinoma-dönüştürmek">Sayıları polinoma dönüştürmek</h2>

<p>Örneğin $1234$ sayısını şu polinomla temsil edebiliriz:</p>

\[A(x)=4+3x+2x^2+x^3\]

<p>Burada $x=10$ seçildiğinde yeniden 1234 elde edilir. İki sayıyı çarpmak, bunlara karşılık gelen polinomları çarpmaya eşdeğerdir. Polinom çarpımındaki katsayılar ise ayrık konvolüsyonla bulunur:</p>

\[c_k=\sum_{i=0}^{k}a_i b_{k-i}\]

<p>Bu formül doğrudan uygulanırsa yine $O(N^2)$ zaman harcar. FFT’nin sihri, konvolüsyonu noktasal çarpıma dönüştürmesidir:</p>

\[\operatorname{FFT}(a*b)=\operatorname{FFT}(a)\cdot\operatorname{FFT}(b)\]

<p>Yani önce katsayıları frekans uzayına taşır, karşılık gelen değerleri tek tek çarpar ve ters FFT ile geri döneriz.</p>

<h2 id="birim-kökler-ve-böl-parçala-yönet">Birim kökler ve böl-parçala-yönet</h2>

<p>Ayrık Fourier Dönüşümü şu şekilde tanımlanır:</p>

\[X_k=\sum_{j=0}^{N-1}x_j e^{-2\pi i jk/N}\]

<p>Üstel ifadeler, karmaşık düzlemde eşit aralıklarla yerleşmiş $N$’inci birim köklerdir. FFT, çift ve tek indeksli katsayıları ayırarak aynı hesaplamaları tekrar yapmaktan kurtulur. Her seviyede toplam $O(N)$ iş yapılır ve yaklaşık $\log_2N$ seviye bulunur.</p>

<table>
  <thead>
    <tr>
      <th>Alan</th>
      <th>İşlem</th>
      <th style="text-align: right">Maliyet</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Katsayı uzayı</td>
      <td>Konvolüsyon</td>
      <td style="text-align: right">$O(N^2)$</td>
    </tr>
    <tr>
      <td>Frekans uzayı</td>
      <td>Noktasal çarpım</td>
      <td style="text-align: right">$O(N)$</td>
    </tr>
    <tr>
      <td>FFT ve ters FFT</td>
      <td>Dönüşüm</td>
      <td style="text-align: right">$O(N\log N)$</td>
    </tr>
  </tbody>
</table>

<h2 id="python-ile-sade-bir-uygulama">Python ile sade bir uygulama</h2>

<p>Aşağıdaki örnek, sayıları onluk basamaklarına ayırır. NumPy FFT hesaplamasını yapar; son döngü ise yuvarlama ve elde taşıma işlemlerini düzeltir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">def</span> <span class="nf">fft_multiply</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
    <span class="n">a</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">array</span><span class="p">([</span><span class="nf">int</span><span class="p">(</span><span class="n">d</span><span class="p">)</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">x</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]],</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
    <span class="n">b</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">array</span><span class="p">([</span><span class="nf">int</span><span class="p">(</span><span class="n">d</span><span class="p">)</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">y</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]],</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>

    <span class="n">size</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="k">while</span> <span class="n">size</span> <span class="o">&lt;</span> <span class="nf">len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">+</span> <span class="nf">len</span><span class="p">(</span><span class="n">b</span><span class="p">):</span>
        <span class="n">size</span> <span class="o">*=</span> <span class="mi">2</span>

    <span class="n">fa</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">fft</span><span class="p">.</span><span class="nf">fft</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">size</span><span class="p">)</span>
    <span class="n">fb</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">fft</span><span class="p">.</span><span class="nf">fft</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">size</span><span class="p">)</span>
    <span class="n">coefficients</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">rint</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">fft</span><span class="p">.</span><span class="nf">ifft</span><span class="p">(</span><span class="n">fa</span> <span class="o">*</span> <span class="n">fb</span><span class="p">).</span><span class="n">real</span><span class="p">).</span><span class="nf">astype</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">int64</span><span class="p">)</span>

    <span class="n">carry</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">digits</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">coefficients</span><span class="p">:</span>
        <span class="n">total</span> <span class="o">=</span> <span class="nf">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">+</span> <span class="n">carry</span>
        <span class="n">digits</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">total</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span>
        <span class="n">carry</span> <span class="o">=</span> <span class="n">total</span> <span class="o">//</span> <span class="mi">10</span>

    <span class="k">while</span> <span class="n">carry</span><span class="p">:</span>
        <span class="n">digits</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">carry</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span>
        <span class="n">carry</span> <span class="o">//=</span> <span class="mi">10</span>

    <span class="k">while</span> <span class="nf">len</span><span class="p">(</span><span class="n">digits</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">digits</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">digits</span><span class="p">.</span><span class="nf">pop</span><span class="p">()</span>

    <span class="k">return</span> <span class="sh">''</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="nf">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">digits</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]))</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">fft_multiply</span><span class="p">(</span><span class="sh">"</span><span class="s">123456789012345</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">987654321098765</span><span class="sh">"</span><span class="p">))</span>
</code></pre></div></div>

<p>Bu uygulama öğreticidir; kayan nokta hataları nedeniyle gerçekten milyonlarca basamakta güvenilir olmayabilir. Pratik sistemler basamakları daha büyük bloklara ayırır veya modüler aritmetik kullanan Sayı Teorik Dönüşümü’nü (NTT) tercih eder. Birden fazla asal modülle yapılan sonuçlar Çin Kalan Teoremi aracılığıyla birleştirilebilir.</p>

<p>Sonuçta FFT yalnızca ses ve görüntü analizi yapan bir araç değildir. Büyük sayı çarpımını polinom çarpımına, polinom çarpımını konvolüsyona ve konvolüsyonu ucuz noktasal çarpımlara dönüştüren güçlü bir algoritmik köprüdür.</p>

<p><img src="/img/fft-ile-dev-80.svg" alt="fft-ile-dev-80" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="fft" /><category term="algoritma" /><category term="matematik" /><category term="python" /><category term="büyük sayılar" /><category term="polinomlar" /><summary type="html"><![CDATA[İlkokulda öğrendiğimiz uzun çarpma yöntemi küçük sayılarda harikadır; ancak milyonlarca basamak söz konusu olduğunda işler dramatik biçimde yavaşlar. Neyse ki sinyal işlemenin yıldızı Hızlı Fourier Dönüşümü, yani FFT, basamakları birer polinom katsayısı gibi ele alarak çarpma işlemini yaklaşık $O(N \log N)$ sürede gerçekleştirebilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/fft-ile-dev-80.png" /><media:content medium="image" url="https://program.sonsuz.us/img/fft-ile-dev-80.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">GNN ile Sosyal Ağların Gizli Topluluklarını Keşfetmek</title><link href="https://program.sonsuz.us/posts/gnn-ile-sosyal-aglarin-gizli-topluluklarini-kesfetmek/" rel="alternate" type="text/html" title="GNN ile Sosyal Ağların Gizli Topluluklarını Keşfetmek" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/gnn-ile-sosyal-aglarin-gizli-topluluklarini-kesfetmek</id><content type="html" xml:base="https://program.sonsuz.us/posts/gnn-ile-sosyal-aglarin-gizli-topluluklarini-kesfetmek/"><![CDATA[<p>Bir sosyal ağı yalnızca “kim kimi takip ediyor?” sorusuyla incelemek, kalabalık bir partide sadece tokalaşmaları saymaya benzer. Oysa arkadaş grupları, ilgi toplulukları ve etkileşim çevreleri bağlantıların oluşturduğu daha büyük desenlerde saklıdır. Graph Neural Networks (GNN), düğüm özellikleriyle ağ yapısını birlikte öğrenerek bu gizli toplulukları ortaya çıkarabilir.</p>

<p>``</p>

<h2 id="sosyal-ağı-graf-olarak-düşünmek">Sosyal ağı graf olarak düşünmek</h2>

<p>Bir sosyal ağ $G=(V,E)$ grafıyla temsil edilir. $V$ kullanıcıları, $E$ ise arkadaşlık, takip veya mesajlaşma gibi ilişkileri gösterir. Her düğümün yaş, ilgi alanı ya da paylaşım sıklığı gibi bir özellik vektörü $x_v$ bulunabilir. Kenarlar da ilişkinin gücü veya türü gibi bilgiler taşıyabilir.</p>

<p>Klasik makine öğrenmesi kullanıcıları çoğunlukla bağımsız örnekler kabul eder. GNN ise “arkadaşının davranışı seni de anlatabilir” fikrinden hareket eder. Her düğüm, komşularından bilgi toplar ve kendi temsiliyle birleştirir. Bu işleme <strong>mesaj geçişi</strong> denir:</p>

\[h_v^{(l+1)} = \sigma\left(W_1h_v^{(l)} + W_2\sum_{u \in N(v)}h_u^{(l)}\right)\]

<p>Burada $h_v^{(l)}$, $v$ düğümünün $l$. katmandaki temsilidir. $N(v)$ komşuları, $W_1$ ve $W_2$ öğrenilen ağırlıklar, $\sigma$ ise doğrusal olmayan aktivasyon fonksiyonudur. Birkaç katman sonunda düğüm yalnızca doğrudan arkadaşlarını değil, arkadaşlarının arkadaşlarını da özetleyen bir gömme (<strong>embedding</strong>) kazanır.</p>

<h2 id="geleneksel-yöntem-mi-gnn-mi">Geleneksel yöntem mi, GNN mi?</h2>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Kullandığı bilgi</th>
      <th>Güçlü yanı</th>
      <th>Sınırlaması</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Louvain</td>
      <td>Ağ bağlantıları</td>
      <td>Hızlı ve etiketsiz çalışır</td>
      <td>Düğüm özelliklerini doğrudan kullanmaz</td>
    </tr>
    <tr>
      <td>Spectral clustering</td>
      <td>Komşuluk matrisi</td>
      <td>Matematiksel olarak güçlüdür</td>
      <td>Büyük ağlarda maliyetlidir</td>
    </tr>
    <tr>
      <td>GNN</td>
      <td>Bağlantılar ve özellikler</td>
      <td>Karmaşık örüntüleri öğrenir</td>
      <td>Eğitim ve hiperparametre ayarı ister</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/gnn-ile-sosyal-78.svg" alt="gnn-ile-sosyal-78" /></p>

<p>GNN doğrudan “topluluk numarası” üretmek zorunda değildir. Önce benzer düğümleri vektör uzayında yakınlaştırır, ardından K-Means gibi bir kümeleme algoritması bu temsilleri gruplandırabilir. Denetimli senaryoda ise bilinen birkaç topluluk etiketiyle düğüm sınıflandırması yapılabilir.</p>

<h2 id="küçük-bir-gcn-uygulaması">Küçük bir GCN uygulaması</h2>

<p>Aşağıdaki model, PyTorch Geometric kullanarak düğümler için sekiz boyutlu temsiller üretir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">torch</span>
<span class="kn">from</span> <span class="n">torch_geometric.nn</span> <span class="kn">import</span> <span class="n">GCNConv</span>

<span class="k">class</span> <span class="nc">CommunityGCN</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">nn</span><span class="p">.</span><span class="n">Module</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">feature_count</span><span class="p">):</span>
        <span class="nf">super</span><span class="p">().</span><span class="nf">__init__</span><span class="p">()</span>
        <span class="n">self</span><span class="p">.</span><span class="n">conv1</span> <span class="o">=</span> <span class="nc">GCNConv</span><span class="p">(</span><span class="n">feature_count</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="n">conv2</span> <span class="o">=</span> <span class="nc">GCNConv</span><span class="p">(</span><span class="mi">32</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">edge_index</span><span class="p">):</span>
        <span class="n">x</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">conv1</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">edge_index</span><span class="p">).</span><span class="nf">relu</span><span class="p">()</span>
        <span class="n">x</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">nn</span><span class="p">.</span><span class="n">functional</span><span class="p">.</span><span class="nf">dropout</span><span class="p">(</span>
            <span class="n">x</span><span class="p">,</span> <span class="n">p</span><span class="o">=</span><span class="mf">0.3</span><span class="p">,</span> <span class="n">training</span><span class="o">=</span><span class="n">self</span><span class="p">.</span><span class="n">training</span>
        <span class="p">)</span>
        <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">conv2</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">edge_index</span><span class="p">)</span>

<span class="n">model</span> <span class="o">=</span> <span class="nc">CommunityGCN</span><span class="p">(</span><span class="n">feature_count</span><span class="o">=</span><span class="mi">16</span><span class="p">)</span>
<span class="n">embeddings</span> <span class="o">=</span> <span class="nf">model</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">data</span><span class="p">.</span><span class="n">edge_index</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">data.x</code>, kullanıcı özelliklerini içeren matrisi; <code class="language-plaintext highlighter-rouge">data.edge_index</code> ise bağlantıları gösterir. İlk GCN katmanı komşuluk bilgisini 32 boyutta işler. İkinci katman, kümelemeye verilebilecek sekiz boyutlu gömmeler oluşturur. Dropout, modelin belirli bağlantılara aşırı güvenmesini azaltır.</p>

<p>Etiketsiz eğitimde bağlantılı düğümlerin gömmelerini yakın, rastgele seçilen bağlantısız düğümleri uzak tutan bir kayıp kullanılabilir. Örneğin iki gömme arasındaki benzerlik $s(u,v)=z_u^Tz_v$ olarak tanımlanabilir. Model, gerçek kenarlarda yüksek; negatif örneklerde düşük skor üretmeyi öğrenir.</p>

<h2 id="başarıyı-nasıl-ölçeriz">Başarıyı nasıl ölçeriz?</h2>

<p>Gerçek topluluk etiketleri varsa NMI, ARI veya F1 skoru kullanılabilir. Etiket yoksa <strong>modülerlik</strong>, aynı topluluktaki bağlantı yoğunluğunu rastlantısal bir ağla karşılaştırır. Yüksek modülerlik iyi bir işaret olsa da tek başına kusursuzluk garantisi değildir; sosyal gruplar örtüşebilir ve kullanıcılar birden fazla topluluğa ait olabilir.</p>

<p>Son olarak gizlilik ve önyargı unutulmamalıdır. GNN, verideki ayrımcı desenleri de öğrenebilir. Bu yüzden anonimleştirme, adalet testleri ve açıklanabilirlik araçları teknik sürecin parçası olmalıdır. Doğru kullanıldığında GNN, bağlantı karmaşasını anlamlı sosyal haritalara dönüştüren oldukça güçlü bir pusuladır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="gnn" /><category term="graf sinir ağları" /><category term="sosyal ağ analizi" /><category term="topluluk tespiti" /><category term="python" /><category term="pytorch geometric" /><summary type="html"><![CDATA[Bir sosyal ağı yalnızca “kim kimi takip ediyor?” sorusuyla incelemek, kalabalık bir partide sadece tokalaşmaları saymaya benzer. Oysa arkadaş grupları, ilgi toplulukları ve etkileşim çevreleri bağlantıların oluşturduğu daha büyük desenlerde saklıdır. Graph Neural Networks (GNN), düğüm özellikleriyle ağ yapısını birlikte öğrenerek bu gizli toplulukları ortaya çıkarabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/gnn-ile-sosyal-78.png" /><media:content medium="image" url="https://program.sonsuz.us/img/gnn-ile-sosyal-78.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Karp’ın Minimum Ortalama Döngü Algoritmasıyla Graflarda Darboğaz Analizi</title><link href="https://program.sonsuz.us/posts/karpin-minimum-ortalama-dongu-algoritmasiyla-graflarda-darbogaz-analizi/" rel="alternate" type="text/html" title="Karp’ın Minimum Ortalama Döngü Algoritmasıyla Graflarda Darboğaz Analizi" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/karpin-minimum-ortalama-dongu-algoritmasiyla-graflarda-darbogaz-analizi</id><content type="html" xml:base="https://program.sonsuz.us/posts/karpin-minimum-ortalama-dongu-algoritmasiyla-graflarda-darbogaz-analizi/"><![CDATA[<p>Bir üretim hattı, işlemci görev zinciri veya ağ yönlendirme sistemi düşünün: İşler belirli durumlar arasında sürekli dolaşıyor ve her geçişin bir maliyeti var. Sistemin uzun vadeli sınırını çoğu zaman tek bir pahalı kenar değil, tekrar tekrar kullanılan bir döngünün ortalama maliyeti belirler. Richard Karp’ın minimum ortalama döngü algoritması, tam olarak bu gizli darboğazı polinom zamanda ortaya çıkarır.</p>

<p><img src="/img/karpin-minimum-ortalama-45.svg" alt="karpin-minimum-ortalama-45" /></p>

<p>``</p>

<h2 id="minimum-ortalama-döngü-nedir">Minimum ortalama döngü nedir?</h2>

<p>Yönlü ve ağırlıklı bir grafı $G=(V,E)$ olarak tanımlayalım. Bir $C$ döngüsünün ortalama ağırlığı, döngüdeki toplam maliyetin kenar sayısına bölünmesidir:</p>

\[μ(C)=\frac{\sum_{e \in C} w(e)}{\vert C\vert }\]

<p>Amaç, bütün yönlü döngüler arasında $μ(C)$ değerini en aza indirmektir. Burada aranan şey toplam ağırlığı en düşük döngü değildir. Örneğin iki kenarlı ve toplam ağırlığı 8 olan bir döngünün ortalaması 4; beş kenarlı ve toplam ağırlığı 10 olan başka bir döngünün ortalaması 2’dir. Toplam maliyeti daha yüksek olan ikinci döngü, uzun vadede daha avantajlıdır.</p>

<table>
  <thead>
    <tr>
      <th>Ölçüt</th>
      <th>Sorduğu soru</th>
      <th>Tipik kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>En kısa yol</td>
      <td>İki nokta arasında en ucuz rota hangisi?</td>
      <td>Navigasyon</td>
    </tr>
    <tr>
      <td>Minimum toplam döngü</td>
      <td>Toplam maliyeti en küçük döngü hangisi?</td>
      <td>Yerel optimizasyon</td>
    </tr>
    <tr>
      <td>Minimum ortalama döngü</td>
      <td>Her tekrar başına en ucuz döngü hangisi?</td>
      <td>Performans sınırı</td>
    </tr>
    <tr>
      <td>Maksimum akış</td>
      <td>Ağdan ne kadar veri geçirilebilir?</td>
      <td>Kapasite analizi</td>
    </tr>
  </tbody>
</table>

<h2 id="karpın-dinamik-programlama-fikri">Karp’ın dinamik programlama fikri</h2>

<p>Grafın $n=\vert V\vert $ düğümü olduğunu varsayalım. Bir başlangıç düğümü $s$ seçilir ve $d_k(v)$, tam olarak $k$ kenar kullanarak $s$ düğümünden $v$ düğümüne ulaşmanın minimum maliyeti olarak tanımlanır:</p>

\[d_k(v)=\min_{(u,v)\in E}\left(d_{k-1}(u)+w(u,v)\right)\]

<p>Başlangıçta $d_0(s)=0$, diğer değerler sonsuzdur. Karp’ın önemli sonucu, güçlü bağlı bir graf için minimum döngü ortalamasını şu formülle verir:</p>

\[μ^*=\min_{v\in V}\max_{0\leq k&lt;n}\frac{d_n(v)-d_k(v)}{n-k}\]

<p>Neden $n$ adım? Çünkü $n$ düğümlü bir graf üzerinde $n$ kenarlık bir yürüyüş mutlaka en az bir düğümü tekrar ziyaret eder; yani içinde bir döngü bulunur. Farklı $k$ noktalarından kalan parçaların ortalamaları karşılaştırıldığında, tekrarın sürdürülebilir en düşük maliyeti görünür hâle gelir.</p>

<h2 id="python-ile-uygulama">Python ile uygulama</h2>

<p>Aşağıdaki kod, düğümleri <code class="language-plaintext highlighter-rouge">0</code> ile <code class="language-plaintext highlighter-rouge">n-1</code> arasında numaralanmış bir graf için minimum ortalama değeri hesaplar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">karp_minimum_cycle_mean</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">edges</span><span class="p">,</span> <span class="n">source</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
    <span class="n">inf</span> <span class="o">=</span> <span class="nf">float</span><span class="p">(</span><span class="sh">"</span><span class="s">inf</span><span class="sh">"</span><span class="p">)</span>
    <span class="n">dp</span> <span class="o">=</span> <span class="p">[[</span><span class="n">inf</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
    <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">source</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="c1"># Tam olarak k kenarlı en ucuz yürüyüşleri hesapla.
</span>    <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">weight</span> <span class="ow">in</span> <span class="n">edges</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">dp</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">u</span><span class="p">]</span> <span class="o">!=</span> <span class="n">inf</span><span class="p">:</span>
                <span class="n">candidate</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">u</span><span class="p">]</span> <span class="o">+</span> <span class="n">weight</span>
                <span class="n">dp</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="nf">min</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">v</span><span class="p">],</span> <span class="n">candidate</span><span class="p">)</span>

    <span class="n">answer</span> <span class="o">=</span> <span class="n">inf</span>
    <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">][</span><span class="n">v</span><span class="p">]</span> <span class="o">==</span> <span class="n">inf</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="n">worst_ratio</span> <span class="o">=</span> <span class="o">-</span><span class="n">inf</span>
        <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">dp</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">v</span><span class="p">]</span> <span class="o">!=</span> <span class="n">inf</span><span class="p">:</span>
                <span class="n">ratio</span> <span class="o">=</span> <span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">][</span><span class="n">v</span><span class="p">]</span> <span class="o">-</span> <span class="n">dp</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">v</span><span class="p">])</span> <span class="o">/</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="n">k</span><span class="p">)</span>
                <span class="n">worst_ratio</span> <span class="o">=</span> <span class="nf">max</span><span class="p">(</span><span class="n">worst_ratio</span><span class="p">,</span> <span class="n">ratio</span><span class="p">)</span>

        <span class="n">answer</span> <span class="o">=</span> <span class="nf">min</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span> <span class="n">worst_ratio</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">answer</span>
</code></pre></div></div>

<p>Dinamik programlama tablosu $n+1$ satır ve $n$ sütun içerir. Her satırda bütün kenarlar gevşetildiği için zaman karmaşıklığı $O(nm)$, bellek karmaşıklığı ise $O(n^2)$ olur. Burada $m=\vert E\vert $ değeridir.</p>

<h2 id="darboğaz-analizindeki-anlamı">Darboğaz analizindeki anlamı</h2>

<p>Ağırlıklar gecikmeyi temsil ediyorsa minimum ortalama döngü, sistemde tekrar başına erişilebilecek en düşük maliyeti gösterir. Ağırlıklar kazanç veya kapasite olarak yorumlanıyorsa işaretleri değiştirerek maksimum ortalama döngü de bulunabilir. Böylece zamanlanmış devrelerde çevrim süresi, üretim ağlarında tekrar maliyeti ve olay sistemlerinde uzun dönem verimi analiz edilebilir.</p>

<p>Algoritmanın verdiği temel sonuç sayısal ortalamadır; döngünün kenarlarını doğrudan döndürmez. Gerçek döngüyü çıkarmak için öncül düğümler saklanmalı ve tekrar eden düğümler geriye doğru izlenmelidir. Ayrıca graf güçlü bağlı değilse her güçlü bağlı bileşeni ayrı incelemek, ulaşılamayan bölgelerin sonucu bozmasını engeller. Kısacası Karp’ın yaklaşımı, “Sistem sonsuza dek çalışırsa hangi tekrar performansı belirler?” sorusuna matematiksel ve uygulanabilir bir cevap verir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="graf algoritmaları" /><category term="karp algoritması" /><category term="dinamik programlama" /><category term="darboğaz analizi" /><category term="python" /><category term="optimizasyon" /><summary type="html"><![CDATA[Bir üretim hattı, işlemci görev zinciri veya ağ yönlendirme sistemi düşünün: İşler belirli durumlar arasında sürekli dolaşıyor ve her geçişin bir maliyeti var. Sistemin uzun vadeli sınırını çoğu zaman tek bir pahalı kenar değil, tekrar tekrar kullanılan bir döngünün ortalama maliyeti belirler. Richard Karp’ın minimum ortalama döngü algoritması, tam olarak bu gizli darboğazı polinom zamanda ortaya çıkarır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/karpin-minimum-ortalama-45.png" /><media:content medium="image" url="https://program.sonsuz.us/img/karpin-minimum-ortalama-45.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">KMP Algoritmasının Çöküşü: Z-Algoritması Neden Bazen Daha Zarif?</title><link href="https://program.sonsuz.us/posts/kmp-algoritmasinin-cokusu-z-algoritmasi-neden-bazen-daha-zarif/" rel="alternate" type="text/html" title="KMP Algoritmasının Çöküşü: Z-Algoritması Neden Bazen Daha Zarif?" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/kmp-algoritmasinin-cokusu-z-algoritmasi-neden-bazen-daha-zarif</id><content type="html" xml:base="https://program.sonsuz.us/posts/kmp-algoritmasinin-cokusu-z-algoritmasi-neden-bazen-daha-zarif/"><![CDATA[<p>Bir metnin içinde desen aramak ilk bakışta basittir: Her konumu dene, karakterleri karşılaştır ve eşleşme bozulunca ilerle. Ancak uzun metinlerde bu yaklaşım pahalılaşır. KMP ve Z-algoritması aynı sorunu doğrusal zamanda çözer; buna rağmen Z dizisi, daha sezgisel tanımı ve farklı problemlere kolay uyarlanması sayesinde kimi zaman KMP’nin meşhur prefix tablosundan daha zarif bir araçtır.</p>

<p><img src="/img/kmp-algoritmasinin-cokusu-90.svg" alt="kmp-algoritmasinin-cokusu-90" /></p>

<p>``</p>

<h2 id="önce-ortak-düşman-gereksiz-karşılaştırmalar">Önce ortak düşman: Gereksiz karşılaştırmalar</h2>

<p>Naif eşleştirmede uzunluğu $n$ olan metin ile uzunluğu $m$ olan desen için en kötü zaman karmaşıklığı $O(nm)$ olabilir. KMP ve Z-algoritması ise daha önce elde edilen eşleşme bilgisini yeniden kullanarak toplam süreyi</p>

\[O(n+m)\]

<p>seviyesine indirir. Yani burada KMP gerçekten “çökmüyor”; başlıktaki çöküş, daha çok zihinsel yüküne yönelik küçük bir dramatizasyondur.</p>

<h2 id="kmp-neden-zor-hissediliyor">KMP neden zor hissediliyor?</h2>

<p>KMP, desen için bir prefix tablosu üretir. Genellikle LPS veya $\pi$ dizisi denilen bu yapı, $\pi[i]$ konumunda desenin aynı zamanda suffix olan en uzun öz prefix’inin uzunluğunu saklar.</p>

<p>Örneğin <code class="language-plaintext highlighter-rouge">ababaca</code> deseninde eşleşme bozulduğunda başa dönmek yerine, prefix tablosu bize desenin hangi bölümünün hâlâ geçerli olduğunu söyler. Fikir güçlüdür; fakat tabloyu oluştururken kullanılan geri dönüş zinciri yeni başlayanları zorlayabilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">pattern</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">pattern</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
    <span class="n">j</span> <span class="o">=</span> <span class="n">pi</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">j = pi[j - 1]</code> satırı algoritmanın kalbidir, ama “Neden tam olarak oraya dönüyoruz?” sorusu çoğu anlatımda havada kalır.</p>

<h2 id="z-dizisinin-daha-görsel-fikri">Z dizisinin daha görsel fikri</h2>

<p>Bir dizge $S$ için $Z[i]$, <code class="language-plaintext highlighter-rouge">S[i:]</code> suffix’i ile bütün dizgenin prefix’i arasındaki en uzun ortak başlangıcın uzunluğudur:</p>

\[Z[i] = \operatorname{LCP}(S, S[i:])\]

<p>Başka bir ifadeyle Z dizisi, her konumda “Buradan başlayan parça, dizgenin başına kaç karakter benziyor?” diye sorar. Metin eşleştirmek için desen ve metni bir ayraçla birleştiririz:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pattern#text
</code></pre></div></div>

<p>Bir konumdaki Z değeri desen uzunluğuna eşitse tam eşleşme bulmuşuzdur. <code class="language-plaintext highlighter-rouge">#</code> karakterinin desen veya metinde bulunmaması gerekir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>KMP</th>
      <th>Z-algoritması</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Temel bilgi</td>
      <td>En uzun prefix-suffix</td>
      <td>Prefix ile konumsal eşleşme</td>
    </tr>
    <tr>
      <td>Arama yapısı</td>
      <td>Desenin tablosu + metin</td>
      <td><code class="language-plaintext highlighter-rouge">desen#metin</code></td>
    </tr>
    <tr>
      <td>Karmaşıklık</td>
      <td>$O(n+m)$</td>
      <td>$O(n+m)$</td>
    </tr>
    <tr>
      <td>Sezgisel soru</td>
      <td>“Nereye geri döneyim?”</td>
      <td>“Başlangıçla kaç karakter aynı?”</td>
    </tr>
    <tr>
      <td>Ek kullanım</td>
      <td>Akış tabanlı arama</td>
      <td>Periyot, tekrar ve sınır analizi</td>
    </tr>
  </tbody>
</table>

<h2 id="orta-düzey-bir-python-uygulaması">Orta düzey bir Python uygulaması</h2>

<p>Aşağıdaki fonksiyon, daha önce hesaplanmış <code class="language-plaintext highlighter-rouge">[left, right]</code> eşleşme kutusunu kullanır. Böylece karakterler gereksiz yere tekrar karşılaştırılmaz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">z_array</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
    <span class="n">z</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="nf">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
    <span class="n">left</span> <span class="o">=</span> <span class="n">right</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">s</span><span class="p">)):</span>
        <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">:</span>
            <span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nf">min</span><span class="p">(</span><span class="n">right</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">z</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="n">left</span><span class="p">])</span>

        <span class="k">while</span> <span class="n">i</span> <span class="o">+</span> <span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="nf">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="ow">and</span> <span class="n">s</span><span class="p">[</span><span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]]:</span>
            <span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">i</span> <span class="o">+</span> <span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">&gt;</span> <span class="n">right</span><span class="p">:</span>
            <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="n">z</span>


<span class="k">def</span> <span class="nf">find_matches</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">pattern</span><span class="p">):</span>
    <span class="n">combined</span> <span class="o">=</span> <span class="n">pattern</span> <span class="o">+</span> <span class="sh">"</span><span class="s">#</span><span class="sh">"</span> <span class="o">+</span> <span class="n">text</span>
    <span class="n">z</span> <span class="o">=</span> <span class="nf">z_array</span><span class="p">(</span><span class="n">combined</span><span class="p">)</span>
    <span class="n">offset</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
    <span class="k">return</span> <span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="n">offset</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">z</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">value</span> <span class="o">==</span> <span class="nf">len</span><span class="p">(</span><span class="n">pattern</span><span class="p">)]</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">find_matches</code>, eşleşmelerin metindeki başlangıç indekslerini döndürür. <code class="language-plaintext highlighter-rouge">[left, right]</code> aralığı bilinen bir prefix eşleşmesini temsil eder; <code class="language-plaintext highlighter-rouge">z[i-left]</code> ise bu hazır bilginin yeni konuma kopyalanabilecek kısmıdır.</p>

<h2 id="peki-hangisini-seçmeliyiz">Peki hangisini seçmeliyiz?</h2>

<p>Metin karakter karakter akıyorsa ve birleşik dizge oluşturmak istemiyorsak KMP doğal bir seçimdir. Bellek davranışı öngörülebilirdir ve klasik arama senaryolarında son derece etkilidir. Buna karşılık tek bir dizgenin tekrarlarını, periyotlarını, border yapılarını veya birçok prefix eşleşmesini incelemek istiyorsak Z dizisi daha doğrudan sonuç verir.</p>

<p>Sonuç olarak Z-algoritması KMP’yi tahtından indirmez. İkisi de doğrusal zamanlıdır; fark, tuttukları bilginin bakış açısındadır. KMP eşleşme bozulduğunda geçmişi yönetir, Z ise her konumu başlangıçla karşılaştırır. Bazen en zarif algoritma daha hızlı olan değil, problemi zihnimizde en az düğümle anlatandır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="algoritma" /><category term="kmp" /><category term="z-algoritması" /><category term="metin-eşleştirme" /><category term="python" /><category term="veri-yapıları" /><summary type="html"><![CDATA[Bir metnin içinde desen aramak ilk bakışta basittir: Her konumu dene, karakterleri karşılaştır ve eşleşme bozulunca ilerle. Ancak uzun metinlerde bu yaklaşım pahalılaşır. KMP ve Z-algoritması aynı sorunu doğrusal zamanda çözer; buna rağmen Z dizisi, daha sezgisel tanımı ve farklı problemlere kolay uyarlanması sayesinde kimi zaman KMP’nin meşhur prefix tablosundan daha zarif bir araçtır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/kmp-algoritmasinin-cokusu-90.png" /><media:content medium="image" url="https://program.sonsuz.us/img/kmp-algoritmasinin-cokusu-90.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Matris Üs Alma ile Devasa Doğrusal Tekrarlamalı Dizileri Hesaplamak</title><link href="https://program.sonsuz.us/posts/matris-us-alma-ile-devasa-dogrusal-tekrarlamali-dizileri-hesaplamak/" rel="alternate" type="text/html" title="Matris Üs Alma ile Devasa Doğrusal Tekrarlamalı Dizileri Hesaplamak" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/matris-us-alma-ile-devasa-dogrusal-tekrarlamali-dizileri-hesaplamak</id><content type="html" xml:base="https://program.sonsuz.us/posts/matris-us-alma-ile-devasa-dogrusal-tekrarlamali-dizileri-hesaplamak/"><![CDATA[<p>Fibonacci dizisinin milyonuncu, hatta milyarıncı terimini hesaplamak istediğimizi düşünelim. Diziyi baştan sona üretmek kolaydır; fakat bilgisayara milyarlarca kez toplama yaptırmak, çay demlenirken başlayıp yeni bir çay plantasyonu kurulunca biten bir plan olabilir. Neyse ki doğrusal tekrarlamaları matris biçiminde ifade ederek problemi $O(n)$ zamandan $O(\log n)$ zamana indirebiliriz.
``
Fibonacci dizisi şu bağıntıyla tanımlanır:</p>

\[F_n = F_{n-1} + F_{n-2}, \qquad F_0=0,\ F_1=1\]

<p>Klasik döngü yaklaşımı, önceki iki değeri saklayıp $F_2$’den $F_n$’e kadar ilerler. Bellek tüketimi $O(1)$ olsa da çalışma süresi $O(n)$ olur. Buradaki kritik gözlem, bir sonraki durumun mevcut durumun <strong>doğrusal dönüşümü</strong> olmasıdır.</p>

<p>Durumumuzu sütun vektörü olarak yazalım:</p>

\[\begin{bmatrix}
F_n \\
F_{n-1}
\end{bmatrix}
=
\begin{bmatrix}
1 &amp; 1 \\
1 &amp; 0
\end{bmatrix}
\begin{bmatrix}
F_{n-1} \\
F_{n-2}
\end{bmatrix}\]

<p>Buradaki dönüşüm matrisi $A$ olsun. Aynı dönüşümü tekrar tekrar uyguladığımızda matris kuvvetleri ortaya çıkar:</p>

\[\begin{bmatrix}
F_n \\
F_{n-1}
\end{bmatrix}
=A^{n-1}
\begin{bmatrix}
F_1 \\
F_0
\end{bmatrix}\]

<p>Yani artık hedefimiz diziyi adım adım yürütmek değil, $A^{n-1}$ matrisini hızlı hesaplamaktır.</p>

<table>
  <thead>
    <tr>
      <th>Yöntem</th>
      <th style="text-align: right">Zaman karmaşıklığı</th>
      <th style="text-align: right">Bellek</th>
      <th>Temel fikir</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Özyinelemeli Fibonacci</td>
      <td style="text-align: right">$O(2^n)$</td>
      <td style="text-align: right">$O(n)$</td>
      <td>Aynı alt problemleri tekrar hesaplar</td>
    </tr>
    <tr>
      <td>Döngü / dinamik programlama</td>
      <td style="text-align: right">$O(n)$</td>
      <td style="text-align: right">$O(1)$</td>
      <td>Terimleri sırayla üretir</td>
    </tr>
    <tr>
      <td>Matris üs alma</td>
      <td style="text-align: right">$O(\log n)$</td>
      <td style="text-align: right">$O(1)$</td>
      <td>Dönüşüm matrisini karesini alarak yükseltir</td>
    </tr>
  </tbody>
</table>

<h2 id="hızlı-üs-alma-neden-logaritmiktir">Hızlı üs alma neden logaritmiktir?</h2>

<p>Bir sayının kuvvetini hesaplarken kullanılan ikili üs alma tekniği matrislerde de geçerlidir. Üs çiftse</p>

\[A^n=(A^{n/2})^2\]

<p>olur. Üs tekse bir adet $A$ dışarı alınır:</p>

\[A^n=A\cdot A^{n-1}\]

<p>Her adımda üs yaklaşık yarıya indiği için yalnızca $\log_2 n$ tur gerekir. Matris boyutu Fibonacci için sabit, yani $2\times2$ olduğundan her çarpım sabit maliyetlidir.</p>

<p>Aşağıdaki C++ kodu sonucu bir modüler sayı altında hesaplar. Mod kullanmak önemlidir; çünkü Fibonacci sayıları son derece hızlı büyür ve standart tam sayı türlerine sığmaz.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="k">const</span> <span class="kt">long</span> <span class="kt">long</span> <span class="n">MOD</span> <span class="o">=</span> <span class="mi">1'000'000'007</span><span class="p">;</span>

<span class="k">struct</span> <span class="nc">Matrix</span> <span class="p">{</span>
    <span class="kt">long</span> <span class="kt">long</span> <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">2</span><span class="p">]{};</span>
<span class="p">};</span>

<span class="n">Matrix</span> <span class="nf">multiply</span><span class="p">(</span><span class="k">const</span> <span class="n">Matrix</span><span class="o">&amp;</span> <span class="n">x</span><span class="p">,</span> <span class="k">const</span> <span class="n">Matrix</span><span class="o">&amp;</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Matrix</span> <span class="n">result</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">)</span>
            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">;</span> <span class="o">++</span><span class="n">k</span><span class="p">)</span>
                <span class="n">result</span><span class="p">.</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span>
                    <span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">+</span> <span class="n">x</span><span class="p">.</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">y</span><span class="p">.</span><span class="n">a</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">j</span><span class="p">])</span> <span class="o">%</span> <span class="n">MOD</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">Matrix</span> <span class="nf">power</span><span class="p">(</span><span class="n">Matrix</span> <span class="n">base</span><span class="p">,</span> <span class="kt">long</span> <span class="kt">long</span> <span class="n">exponent</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Matrix</span> <span class="n">result</span><span class="p">;</span>
    <span class="n">result</span><span class="p">.</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">result</span><span class="p">.</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// Birim matris</span>

    <span class="k">while</span> <span class="p">(</span><span class="n">exponent</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">exponent</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span>
            <span class="n">result</span> <span class="o">=</span> <span class="n">multiply</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">base</span><span class="p">);</span>
        <span class="n">base</span> <span class="o">=</span> <span class="n">multiply</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">base</span><span class="p">);</span>
        <span class="n">exponent</span> <span class="o">&gt;&gt;=</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">long</span> <span class="kt">long</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="kt">long</span> <span class="kt">long</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">Matrix</span> <span class="n">transition</span><span class="p">{{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">},</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">}}};</span>
    <span class="k">return</span> <span class="n">power</span><span class="p">(</span><span class="n">transition</span><span class="p">,</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">).</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">fibonacci</span><span class="p">(</span><span class="mi">1'000'000'000</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">multiply</code> iki dönüşümü birleştirir; <code class="language-plaintext highlighter-rouge">power</code> ise üssün ikili gösterimini kullanır. Başlangıçta sonuç birim matristir, çünkü $A^0=I$ olmalıdır. Üssün ilgili biti bir olduğunda mevcut taban sonuca katılır.</p>

<h2 id="yalnızca-fibonacci-değil">Yalnızca Fibonacci değil</h2>

<p>Bu yöntem, sabit katsayılı her doğrusal tekrarlamaya uygulanabilir. Örneğin</p>

\[X_n=2X_{n-1}+3X_{n-2}\]

<p>için dönüşüm matrisi</p>

\[\begin{bmatrix}
2 &amp; 3 \\
1 &amp; 0
\end{bmatrix}\]

<p>olur. Daha fazla geçmiş terime bağlı bağıntılarda matris boyutu büyür; mantık değişmez. Böylece matris, dizinin hafızasını taşıyan küçük bir zaman makinesine dönüşür: milyarlarca adımı tek tek yürümek yerine onları logaritmik sayıda sıçramayla geçer.</p>

<p><img src="/img/matris-us-alma-18.svg" alt="matris-us-alma-18" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="matris" /><category term="fibonacci" /><category term="algoritma" /><category term="dinamik-programlama" /><category term="hızlı-üs-alma" /><category term="c++" /><summary type="html"><![CDATA[Fibonacci dizisinin milyonuncu, hatta milyarıncı terimini hesaplamak istediğimizi düşünelim. Diziyi baştan sona üretmek kolaydır; fakat bilgisayara milyarlarca kez toplama yaptırmak, çay demlenirken başlayıp yeni bir çay plantasyonu kurulunca biten bir plan olabilir. Neyse ki doğrusal tekrarlamaları matris biçiminde ifade ederek problemi $O(n)$ zamandan $O(\log n)$ zamana indirebiliriz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/matris-us-alma-18.png" /><media:content medium="image" url="https://program.sonsuz.us/img/matris-us-alma-18.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Min-Cost Max-Flow: Kapasite ve Maliyeti Aynı Anda Optimize Etmek</title><link href="https://program.sonsuz.us/posts/min-cost-max-flow-kapasite-ve-maliyeti-ayni-anda-optimize-etmek/" rel="alternate" type="text/html" title="Min-Cost Max-Flow: Kapasite ve Maliyeti Aynı Anda Optimize Etmek" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/min-cost-max-flow-kapasite-ve-maliyeti-ayni-anda-optimize-etmek</id><content type="html" xml:base="https://program.sonsuz.us/posts/min-cost-max-flow-kapasite-ve-maliyeti-ayni-anda-optimize-etmek/"><![CDATA[<p>Bir lojistik ağında mümkün olan en fazla ürünü taşımak yetmez; bunu hangi maliyetle yaptığınız da önemlidir. <strong>Min-Cost Max-Flow (MCMF)</strong>, kaynaktan hedefe maksimum akışı gönderirken toplam taşıma maliyetini en aza indiren algoritma ailesidir. Kısacası maksimum performans ile minimum fatura arasında matematiksel bir barış anlaşması imzalar.</p>

<p><img src="/img/min-cost-max-80.svg" alt="min-cost-max-80" /></p>

<p>``</p>

<h2 id="problemin-matematiksel-modeli">Problemin matematiksel modeli</h2>

<p>Yönlü bir ağdaki her $(u,v)$ kenarı iki değere sahiptir: kapasite $c(u,v)$ ve birim akış maliyeti $w(u,v)$. Kenardan geçirilen akış $f(u,v)$ ise şu koşulu sağlamalıdır:</p>

\[0 \leq f(u,v) \leq c(u,v)\]

<p>Kaynak $s$ ve hedef $t$ dışındaki her düğümde akış korunur:</p>

\[\sum_u f(u,v)=\sum_x f(v,x)\]

<p>Önce toplam akış miktarı $F$ maksimize edilir, ardından bu akışın maliyeti minimize edilir:</p>

\[C=\sum_{(u,v)\in E} f(u,v)\cdot w(u,v)\]

<p>Bu öncelik önemlidir. Sadece en ucuz yolu seçmek maksimum akışa ulaşmayı engelleyebilir; sadece maksimum akış bulmak ise gereksiz derecede pahalı bir sonuç üretebilir.</p>

<table>
  <thead>
    <tr>
      <th>Problem</th>
      <th>Amaç</th>
      <th>Kenar bilgisi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>En kısa yol</td>
      <td>En ucuz tek rota</td>
      <td>Maliyet</td>
    </tr>
    <tr>
      <td>Maximum Flow</td>
      <td>En yüksek akış</td>
      <td>Kapasite</td>
    </tr>
    <tr>
      <td>Min-Cost Flow</td>
      <td>Belirli akışı ucuza taşıma</td>
      <td>Kapasite ve maliyet</td>
    </tr>
    <tr>
      <td>Min-Cost Max-Flow</td>
      <td>Maksimum akışı en ucuza taşıma</td>
      <td>Kapasite ve maliyet</td>
    </tr>
  </tbody>
</table>

<h2 id="artık-ağ-neden-gereklidir">Artık ağ neden gereklidir?</h2>

<p>Algoritma her seçimden sonra bir <strong>artık ağ (residual graph)</strong> tutar. Kapasitesi kullanılan ileri kenarın artık kapasitesi azalır; ters yönde ise maliyeti $-w(u,v)$ olan bir kenar oluşur. Bu ters kenar, algoritmanın önceki kararından vazgeçebilmesini sağlar. Yani sistem yalnızca ilerlemez; gerektiğinde “Bu rota pek iyi olmadı” diyerek akışı geri alıp daha ucuz biçimde düzenler.</p>

<p>Yaygın yaklaşım, artık ağda maliyeti en düşük artırma yolunu bulup mümkün olan akışı bu yoldan göndermektir. Negatif kenarlar nedeniyle Bellman-Ford kullanılabilir. Daha hızlı uygulamalarda ise düğüm potansiyelleriyle maliyetler yeniden ağırlıklandırılır ve Dijkstra çalıştırılır.</p>

<p>İndirgenmiş maliyet şu şekilde hesaplanır:</p>

\[w'(u,v)=w(u,v)+p(u)-p(v)\]

<p>Doğru potansiyeller altında $w’(u,v)\geq 0$ olur; böylece Dijkstra güvenle kullanılabilir.</p>

<h2 id="python-ile-temel-uygulama">Python ile temel uygulama</h2>

<p>Aşağıdaki sürüm, anlaşılır olması için SPFA ile en ucuz artırma yolunu bulur:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">collections</span> <span class="kn">import</span> <span class="n">deque</span>

<span class="k">class</span> <span class="nc">Edge</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">to</span><span class="p">,</span> <span class="n">rev</span><span class="p">,</span> <span class="n">cap</span><span class="p">,</span> <span class="n">cost</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">to</span><span class="p">,</span> <span class="n">self</span><span class="p">.</span><span class="n">rev</span> <span class="o">=</span> <span class="n">to</span><span class="p">,</span> <span class="n">rev</span>
        <span class="n">self</span><span class="p">.</span><span class="n">cap</span><span class="p">,</span> <span class="n">self</span><span class="p">.</span><span class="n">cost</span> <span class="o">=</span> <span class="n">cap</span><span class="p">,</span> <span class="n">cost</span>

<span class="k">def</span> <span class="nf">add_edge</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">cap</span><span class="p">,</span> <span class="n">cost</span><span class="p">):</span>
    <span class="n">g</span><span class="p">[</span><span class="n">u</span><span class="p">].</span><span class="nf">append</span><span class="p">(</span><span class="nc">Edge</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">g</span><span class="p">[</span><span class="n">v</span><span class="p">]),</span> <span class="n">cap</span><span class="p">,</span> <span class="n">cost</span><span class="p">))</span>
    <span class="n">g</span><span class="p">[</span><span class="n">v</span><span class="p">].</span><span class="nf">append</span><span class="p">(</span><span class="nc">Edge</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">g</span><span class="p">[</span><span class="n">u</span><span class="p">])</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="n">cost</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">min_cost_max_flow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">source</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
    <span class="n">n</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
    <span class="n">flow</span> <span class="o">=</span> <span class="n">cost</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="n">dist</span> <span class="o">=</span> <span class="p">[</span><span class="nf">float</span><span class="p">(</span><span class="sh">'</span><span class="s">inf</span><span class="sh">'</span><span class="p">)]</span> <span class="o">*</span> <span class="n">n</span>
        <span class="n">parent</span> <span class="o">=</span> <span class="p">[</span><span class="bp">None</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span>
        <span class="n">in_queue</span> <span class="o">=</span> <span class="p">[</span><span class="bp">False</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span>
        <span class="n">dist</span><span class="p">[</span><span class="n">source</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">q</span> <span class="o">=</span> <span class="nf">deque</span><span class="p">([</span><span class="n">source</span><span class="p">])</span>

        <span class="k">while</span> <span class="n">q</span><span class="p">:</span>
            <span class="n">u</span> <span class="o">=</span> <span class="n">q</span><span class="p">.</span><span class="nf">popleft</span><span class="p">()</span>
            <span class="n">in_queue</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">=</span> <span class="bp">False</span>
            <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">g</span><span class="p">[</span><span class="n">u</span><span class="p">]):</span>
                <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="n">cap</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">dist</span><span class="p">[</span><span class="n">e</span><span class="p">.</span><span class="n">to</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">dist</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">+</span> <span class="n">e</span><span class="p">.</span><span class="n">cost</span><span class="p">:</span>
                    <span class="n">dist</span><span class="p">[</span><span class="n">e</span><span class="p">.</span><span class="n">to</span><span class="p">]</span> <span class="o">=</span> <span class="n">dist</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">+</span> <span class="n">e</span><span class="p">.</span><span class="n">cost</span>
                    <span class="n">parent</span><span class="p">[</span><span class="n">e</span><span class="p">.</span><span class="n">to</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
                    <span class="k">if</span> <span class="ow">not</span> <span class="n">in_queue</span><span class="p">[</span><span class="n">e</span><span class="p">.</span><span class="n">to</span><span class="p">]:</span>
                        <span class="n">q</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">to</span><span class="p">)</span>
                        <span class="n">in_queue</span><span class="p">[</span><span class="n">e</span><span class="p">.</span><span class="n">to</span><span class="p">]</span> <span class="o">=</span> <span class="bp">True</span>

        <span class="k">if</span> <span class="n">parent</span><span class="p">[</span><span class="n">target</span><span class="p">]</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="k">break</span>

        <span class="n">pushed</span> <span class="o">=</span> <span class="nf">float</span><span class="p">(</span><span class="sh">'</span><span class="s">inf</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">v</span> <span class="o">=</span> <span class="n">target</span>
        <span class="k">while</span> <span class="n">v</span> <span class="o">!=</span> <span class="n">source</span><span class="p">:</span>
            <span class="n">u</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="n">parent</span><span class="p">[</span><span class="n">v</span><span class="p">]</span>
            <span class="n">pushed</span> <span class="o">=</span> <span class="nf">min</span><span class="p">(</span><span class="n">pushed</span><span class="p">,</span> <span class="n">g</span><span class="p">[</span><span class="n">u</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">cap</span><span class="p">)</span>
            <span class="n">v</span> <span class="o">=</span> <span class="n">u</span>

        <span class="n">v</span> <span class="o">=</span> <span class="n">target</span>
        <span class="k">while</span> <span class="n">v</span> <span class="o">!=</span> <span class="n">source</span><span class="p">:</span>
            <span class="n">u</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="n">parent</span><span class="p">[</span><span class="n">v</span><span class="p">]</span>
            <span class="n">e</span> <span class="o">=</span> <span class="n">g</span><span class="p">[</span><span class="n">u</span><span class="p">][</span><span class="n">i</span><span class="p">]</span>
            <span class="n">e</span><span class="p">.</span><span class="n">cap</span> <span class="o">-=</span> <span class="n">pushed</span>
            <span class="n">g</span><span class="p">[</span><span class="n">v</span><span class="p">][</span><span class="n">e</span><span class="p">.</span><span class="n">rev</span><span class="p">].</span><span class="n">cap</span> <span class="o">+=</span> <span class="n">pushed</span>
            <span class="n">cost</span> <span class="o">+=</span> <span class="n">pushed</span> <span class="o">*</span> <span class="n">e</span><span class="p">.</span><span class="n">cost</span>
            <span class="n">v</span> <span class="o">=</span> <span class="n">u</span>

        <span class="n">flow</span> <span class="o">+=</span> <span class="n">pushed</span>

    <span class="k">return</span> <span class="n">flow</span><span class="p">,</span> <span class="n">cost</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">add_edge</code>, ileri kenarla birlikte ters kenarı da oluşturur. Ana döngü en ucuz yolu bulur, yol üzerindeki darboğaz kapasiteyi hesaplar ve artık ağı günceller. Sonuç <code class="language-plaintext highlighter-rouge">(maksimum_akış, minimum_maliyet)</code> biçimindedir.</p>

<h2 id="karmaşıklık-ve-kullanım-alanları">Karmaşıklık ve kullanım alanları</h2>

<p>SPFA tabanlı yaklaşım pratikte kullanışlı olsa da en kötü durumda yavaşlayabilir. Bellman-Ford ile yaklaşık $O(FVE)$, potansiyel ve Dijkstra ile $O(FE\log V)$ davranışı beklenir; burada $F$ artırma sayısıyla ilişkilidir.</p>

<p>MCMF; kargo dağıtımı, çalışan-görev eşleştirmesi, üretim planlama, ağ paketlerinin yönlendirilmesi ve kaynak tahsisi gibi alanlarda kullanılır. Özetle soru “Ne kadar taşıyabilirim?” ile bitmiyor, “Bunu en akıllıca kaça taşırım?” diye devam ediyorsa sahne Min-Cost Max-Flow’undur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="algoritma" /><category term="graf" /><category term="ağ-akışı" /><category term="optimizasyon" /><category term="python" /><category term="min-cost-max-flow" /><summary type="html"><![CDATA[Bir lojistik ağında mümkün olan en fazla ürünü taşımak yetmez; bunu hangi maliyetle yaptığınız da önemlidir. Min-Cost Max-Flow (MCMF), kaynaktan hedefe maksimum akışı gönderirken toplam taşıma maliyetini en aza indiren algoritma ailesidir. Kısacası maksimum performans ile minimum fatura arasında matematiksel bir barış anlaşması imzalar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/min-cost-max-80.png" /><media:content medium="image" url="https://program.sonsuz.us/img/min-cost-max-80.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mo Algoritmasını Ağaçlara Uyarlamak: Euler Turu ile Çevrimdışı Sorgular</title><link href="https://program.sonsuz.us/posts/mo-algoritmasini-agaclara-uyarlamak-euler-turu-ile-cevrimdisi-sorgular/" rel="alternate" type="text/html" title="Mo Algoritmasını Ağaçlara Uyarlamak: Euler Turu ile Çevrimdışı Sorgular" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/mo-algoritmasini-agaclara-uyarlamak-euler-turu-ile-cevrimdisi-sorgular</id><content type="html" xml:base="https://program.sonsuz.us/posts/mo-algoritmasini-agaclara-uyarlamak-euler-turu-ile-cevrimdisi-sorgular/"><![CDATA[<p>Bir dizideki aralık sorgularını akıllıca sıralayıp tekrar kullanılabilir hesaplarla hızlandıran Mo algoritması, küçük bir Euler turu numarasıyla ağaçlarda da çalışabilir. Özellikle iki düğüm arasındaki yolda kaç farklı renk bulunduğu gibi sorgular, ağacı doğrusal bir yapıya dönüştürdüğümüzde bloklar hâlinde işlenebilir.</p>

<p><img src="/img/mo-algoritmasini-agaclara-19.svg" alt="mo-algoritmasini-agaclara-19" /></p>

<p>``</p>

<h2 id="önce-klasik-mo-mantığı">Önce klasik Mo mantığı</h2>

<p>Elimizde $Q$ adet $[L,R]$ sorgusu bulunan, uzunluğu $N$ olan bir dizi düşünelim. Her sorguyu bağımsız çözmek pahalıdır. Mo algoritması sorguları önce $L$ değerinin ait olduğu bloğa, ardından $R$ değerine göre sıralar. Blok boyutu genellikle $B \approx \sqrt{N}$ seçilir.</p>

<p>İki işaretçiyle güncel aralığı koruruz. Yeni sorguya geçerken elemanları yalnızca ekler veya çıkarırız. Ekleme ve çıkarma $O(1)$ ise yaklaşık karmaşıklık şöyledir:</p>

\[O((N+Q)\sqrt{N})\]

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Sorgu sırası</th>
      <th>Ara sonuç kullanımı</th>
      <th>Yaklaşık maliyet</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bağımsız çözüm</td>
      <td>Geliş sırası</td>
      <td>Yok</td>
      <td>$O(NQ)$</td>
    </tr>
    <tr>
      <td>Dizi üzerinde Mo</td>
      <td>Blok sırası</td>
      <td>Var</td>
      <td>$O((N+Q)\sqrt N)$</td>
    </tr>
    <tr>
      <td>Ağaç üzerinde Mo</td>
      <td>Euler aralıkları</td>
      <td>Var</td>
      <td>Genellikle $O((N+Q)\sqrt N)$</td>
    </tr>
  </tbody>
</table>

<h2 id="ağacı-diziye-çevirmek">Ağacı diziye çevirmek</h2>

<p>Ağaçta iki düğüm arasındaki yol doğrudan tek bir dizi aralığı değildir. Çözüm, DFS sırasında oluşturulan <strong>Euler turudur</strong>. Her düğümü ağaca girerken ve düğümden çıkarken kaydederiz. Böylece $N$ düğümlü ağaç için $2N$ uzunluğunda bir dizi oluşur.</p>

<p>Bir düğümün Euler aralığında kaç kez göründüğüne dikkat ederiz:</p>

<ul>
  <li>Bir kez görünüyorsa etkin kümededir.</li>
  <li>İki kez görünüyorsa iki ziyaret birbirini götürür.</li>
  <li>Hiç görünmüyorsa sorgunun yolunda değildir.</li>
</ul>

<p>Bu nedenle işaretçi bir Euler konumuna geldiğinde düğümü doğrudan eklemek yerine durumunu <strong>toggle</strong>, yani aç/kapat yaparız. Bu yaklaşım biraz ışık anahtarına benzer: aynı düğmeye ikinci kez basınca oda eski hâline döner.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">euler</span><span class="p">,</span> <span class="n">color</span><span class="p">,</span> <span class="n">freq</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">&gt;</span> <span class="n">active</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">distinctColors</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">toggle</span><span class="p">(</span><span class="kt">int</span> <span class="n">position</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">node</span> <span class="o">=</span> <span class="n">euler</span><span class="p">[</span><span class="n">position</span><span class="p">];</span>
    <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="n">color</span><span class="p">[</span><span class="n">node</span><span class="p">];</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">active</span><span class="p">[</span><span class="n">node</span><span class="p">])</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">--</span><span class="n">freq</span><span class="p">[</span><span class="n">c</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="n">distinctColors</span><span class="o">--</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">freq</span><span class="p">[</span><span class="n">c</span><span class="p">]</span><span class="o">++</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="n">distinctColors</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">active</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="o">!</span><span class="n">active</span><span class="p">[</span><span class="n">node</span><span class="p">];</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">freq[c]</code>, etkin düğümler arasında <code class="language-plaintext highlighter-rouge">c</code> renginin kaç defa bulunduğunu tutar. <code class="language-plaintext highlighter-rouge">distinctColors</code> ise güncel yol üzerindeki farklı renk sayısıdır. Renk değerleri büyükse önce koordinat sıkıştırma uygulanmalıdır.</p>

<h2 id="lca-neden-gerekiyor">LCA neden gerekiyor?</h2>

<p>$u$ ve $v$ düğümleri için önce giriş zamanlarına göre sıralama yapılır. Eğer $u$, $v$ düğümünün atasıysa yol uygun bir Euler aralığıyla temsil edilir. Değilse aralık, yolun büyük bölümünü kapsar fakat $LCA(u,v)$ düğümünü dışarıda bırakır.</p>

<p>Bu durumda sorgu cevaplanmadan hemen önce LCA geçici olarak etkinleştirilir, sonuç kaydedilir ve ardından tekrar kapatılır. İkili kaldırma kullanıldığında LCA hesabı $O(\log N)$ sürede yapılabilir.</p>

<table>
  <thead>
    <tr>
      <th>Durum</th>
      <th>Mo aralığı</th>
      <th>Ek işlem</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$u$, $v$’nin atası</td>
      <td><code class="language-plaintext highlighter-rouge">tin[u]..tin[v]</code></td>
      <td>Yok</td>
    </tr>
    <tr>
      <td>Ayrı dallardalar</td>
      <td><code class="language-plaintext highlighter-rouge">tout[u]..tin[v]</code></td>
      <td>LCA geçici eklenir</td>
    </tr>
  </tbody>
</table>

<h2 id="sorguları-sıralamak">Sorguları sıralamak</h2>

<p>Her yol sorgusu, hesaplanan sol ve sağ Euler sınırlarıyla saklanır. Sonra klasik blok karşılaştırması uygulanır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sort</span><span class="p">(</span><span class="n">queries</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">queries</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="p">[</span><span class="o">&amp;</span><span class="p">](</span><span class="k">const</span> <span class="n">Query</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="n">Query</span><span class="o">&amp;</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">blockA</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">left</span> <span class="o">/</span> <span class="n">blockSize</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">blockB</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">left</span> <span class="o">/</span> <span class="n">blockSize</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">blockA</span> <span class="o">!=</span> <span class="n">blockB</span><span class="p">)</span> <span class="k">return</span> <span class="n">blockA</span> <span class="o">&lt;</span> <span class="n">blockB</span><span class="p">;</span>

    <span class="c1">// Zikzak sıralama sağ işaretçinin hareketini azaltır.</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">blockA</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="k">return</span> <span class="n">a</span><span class="p">.</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">b</span><span class="p">.</span><span class="n">right</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">a</span><span class="p">.</span><span class="n">right</span> <span class="o">&lt;</span> <span class="n">b</span><span class="p">.</span><span class="n">right</span><span class="p">;</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Ağaç üzerinde Mo algoritması çevrimdışıdır; cevap vermeden önce bütün sorguları bilmek gerekir. Buna karşılık güncelleme bulunmayan, çok sayıda yol sorgusu içeren problemlerde oldukça güçlüdür. Özet tarif şudur: ağacı Euler turuyla düzleştir, sorguları bloklara ayır, düğümleri toggle et ve LCA’nın eksik kaldığı köşeleri dikkatle tamamla. Gerisi, iki işaretçinin ormanda düzenli bir yürüyüşünden ibarettir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="mo algoritması" /><category term="ağaç algoritmaları" /><category term="euler turu" /><category term="lca" /><category term="çevrimdışı sorgu" /><category term="c++" /><summary type="html"><![CDATA[Bir dizideki aralık sorgularını akıllıca sıralayıp tekrar kullanılabilir hesaplarla hızlandıran Mo algoritması, küçük bir Euler turu numarasıyla ağaçlarda da çalışabilir. Özellikle iki düğüm arasındaki yolda kaç farklı renk bulunduğu gibi sorgular, ağacı doğrusal bir yapıya dönüştürdüğümüzde bloklar hâlinde işlenebilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/mo-algoritmasini-agaclara-19.png" /><media:content medium="image" url="https://program.sonsuz.us/img/mo-algoritmasini-agaclara-19.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Möbius İnversiyonu ile Sayılar Teorisinde Kapsama-Dışlama</title><link href="https://program.sonsuz.us/posts/mobius-inversiyonu-ile-sayilar-teorisinde-kapsama-dislama/" rel="alternate" type="text/html" title="Möbius İnversiyonu ile Sayılar Teorisinde Kapsama-Dışlama" /><published>2026-09-25T00:00:00+00:00</published><updated>2026-09-25T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/mobius-inversiyonu-ile-sayilar-teorisinde-kapsama-dislama</id><content type="html" xml:base="https://program.sonsuz.us/posts/mobius-inversiyonu-ile-sayilar-teorisinde-kapsama-dislama/"><![CDATA[<p>Bazı sayılar teorisi problemleri, bölenlerin ve ortak çarpanların iç içe geçmesi yüzünden çözülmez bir düğüm gibi görünür. Möbius inversiyonu ise bu düğümü tek tek açmak yerine matematiksel olarak tersine çevirir. Aralarında asal çiftleri saymaktan bölen toplamlarından özgün bir fonksiyonu geri kazanmaya kadar pek çok işlem, böylece zarif bir kapsama-dışlama hesabına dönüşür.</p>

<p><img src="/img/mobius-inversiyonu-ile-53.svg" alt="mobius-inversiyonu-ile-53" /></p>

<p>``</p>
<h2 id="möbius-fonksiyonu-nedir">Möbius fonksiyonu nedir?</h2>

<p>Möbius fonksiyonu $\mu(n)$, pozitif tam sayıları üç gruba ayırır:</p>

\[\mu(n)=
\begin{cases}
1, &amp; n=1,\\
0, &amp; n \text{ bir asalın karesine bölünüyorsa},\\
(-1)^k, &amp; n \text{ farklı } k \text{ asalın çarpımıysa}.
\end{cases}\]

<p>Örneğin $\mu(6)=1$ olur; çünkü $6=2\cdot3$ ve iki farklı asal çarpanı vardır. Buna karşılık $12$, $2^2$ ile bölündüğü için $\mu(12)=0$ değerini alır.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">$n$</th>
      <th>Asal çarpan yapısı</th>
      <th style="text-align: right">$\mu(n)$</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">1</td>
      <td>Boş çarpım</td>
      <td style="text-align: right">1</td>
    </tr>
    <tr>
      <td style="text-align: right">6</td>
      <td>$2\cdot3$</td>
      <td style="text-align: right">1</td>
    </tr>
    <tr>
      <td style="text-align: right">30</td>
      <td>$2\cdot3\cdot5$</td>
      <td style="text-align: right">-1</td>
    </tr>
    <tr>
      <td style="text-align: right">12</td>
      <td>$2^2\cdot3$</td>
      <td style="text-align: right">0</td>
    </tr>
  </tbody>
</table>

<p>Fonksiyonun sihirli özelliği şudur:</p>

\[\sum_{d\mid n}\mu(d)=
\begin{cases}
1, &amp; n=1,\\
0, &amp; n&gt;1.
\end{cases}\]

<p>Bu eşitlik, istenmeyen ortak bölenleri artı ve eksi işaretlerle yok eden kapsama-dışlama ilkesinin aritmetik karşılığıdır.</p>

<h2 id="möbius-inversiyon-formülü">Möbius inversiyon formülü</h2>

<p>Bir $f$ fonksiyonunun bölenler üzerindeki toplamıyla $g$ fonksiyonu tanımlansın:</p>

\[g(n)=\sum_{d\mid n}f(d).\]

<p>Möbius inversiyonu, toplamın içine saklanmış $f$ değerini geri çıkarır:</p>

\[f(n)=\sum_{d\mid n}\mu(d)g\left(\frac{n}{d}\right).\]

<table>
  <thead>
    <tr>
      <th>İleri işlem</th>
      <th>Ters işlem</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bölenlerden bilgi toplar</td>
      <td>Toplanan bilgiyi ayrıştırır</td>
    </tr>
    <tr>
      <td>$g(n)=\sum_{d\mid n}f(d)$</td>
      <td>$f(n)=\sum_{d\mid n}\mu(d)g(n/d)$</td>
    </tr>
    <tr>
      <td>Birikimli görünüm üretir</td>
      <td>Özgün katkıları bulur</td>
    </tr>
  </tbody>
</table>

<p>Bunun klasik örneği Euler’in totient fonksiyonudur. $n$ sayısının pozitif bölenlerinin totient değerleri toplamı $n$ eder:</p>

\[n=\sum_{d\mid n}\varphi(d).\]

<p>İnversiyon uygulandığında doğrudan şu formül elde edilir:</p>

\[\varphi(n)=\sum_{d\mid n}\mu(d)\frac{n}{d}.\]

<h2 id="aralarında-asal-çiftleri-saymak">Aralarında asal çiftleri saymak</h2>

<p>$1\leq a,b\leq N$ koşulunu sağlayan ve $\gcd(a,b)=1$ olan sıralı çiftleri sayalım. Bir çiftin her iki elemanı da $d$ ile bölünüyorsa yaklaşık değil, tam olarak $\lfloor N/d\rfloor^2$ seçenek vardır. Möbius fonksiyonu ortak bölenleri kapsama-dışlama ile temizler:</p>

\[C(N)=\sum_{d=1}^{N}\mu(d)\left\lfloor\frac{N}{d}\right\rfloor^2.\]

<p>Burada $\mu(d)=0$ olan kare çarpanlı değerler otomatik olarak elenir. Tek sayıda farklı asal içerenler çıkarılır, çift sayıda asal içerenler yeniden eklenir. Kısacası Möbius fonksiyonu, kapsama-dışlamanın muhasebecisidir; üstelik hesap makinesini hiç düşürmez!</p>

<h2 id="python-ile-doğrusal-elek">Python ile doğrusal elek</h2>

<p>Aşağıdaki kod, $1$ ile $N$ arasındaki Möbius değerlerini doğrusal zamanda üretir ve aralarında asal sıralı çiftlerin sayısını hesaplar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">mobius_sieve</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">mu</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">mu</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="n">primes</span><span class="p">,</span> <span class="n">composite</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[</span><span class="bp">False</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">composite</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
            <span class="n">primes</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
            <span class="n">mu</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
        <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">primes</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">*</span> <span class="n">p</span> <span class="o">&gt;</span> <span class="n">n</span><span class="p">:</span>
                <span class="k">break</span>
            <span class="n">composite</span><span class="p">[</span><span class="n">i</span> <span class="o">*</span> <span class="n">p</span><span class="p">]</span> <span class="o">=</span> <span class="bp">True</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="n">p</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">mu</span><span class="p">[</span><span class="n">i</span> <span class="o">*</span> <span class="n">p</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
                <span class="k">break</span>
            <span class="n">mu</span><span class="p">[</span><span class="n">i</span> <span class="o">*</span> <span class="n">p</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">mu</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">mu</span>


<span class="k">def</span> <span class="nf">coprime_pairs</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">mu</span> <span class="o">=</span> <span class="nf">mobius_sieve</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
    <span class="k">return</span> <span class="nf">sum</span><span class="p">(</span><span class="n">mu</span><span class="p">[</span><span class="n">d</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">//</span> <span class="n">d</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">coprime_pairs</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span>  <span class="c1"># 63
</span></code></pre></div></div>

<p>Elek her bileşik sayıyı kontrollü biçimde işler; böylece karmaşıklık $O(N)$, toplam hesabı da $O(N)$ olur. Büyük sınırlar için $\lfloor N/d\rfloor$ değerlerinin yalnızca yaklaşık $2\sqrt N$ farklı değer aldığından yararlanılarak gruplama yapılabilir.</p>

<p>Möbius inversiyonunu gördüğünüzde temel soruyu sorun: “Elimdeki fonksiyon, bölenler üzerinden birikmiş başka bir bilginin toplamı mı?” Yanıt evetse, tersine çevirme formülü büyük olasılıkla problemi birkaç satırlık temiz bir toplama indirecektir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="möbius inversiyonu" /><category term="sayılar teorisi" /><category term="kapsama-dışlama" /><category term="aralarında asallık" /><category term="bölen toplamları" /><category term="algoritma" /><summary type="html"><![CDATA[Bazı sayılar teorisi problemleri, bölenlerin ve ortak çarpanların iç içe geçmesi yüzünden çözülmez bir düğüm gibi görünür. Möbius inversiyonu ise bu düğümü tek tek açmak yerine matematiksel olarak tersine çevirir. Aralarında asal çiftleri saymaktan bölen toplamlarından özgün bir fonksiyonu geri kazanmaya kadar pek çok işlem, böylece zarif bir kapsama-dışlama hesabına dönüşür.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/mobius-inversiyonu-ile-53.png" /><media:content medium="image" url="https://program.sonsuz.us/img/mobius-inversiyonu-ile-53.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>