<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet href="/feed.xsl" type="text/xsl"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Tag: Heuristic Algorithm - Nguyen Cung Thanh</title><id>https://nguyencungthanh.github.io/tags/heuristic-algorithm/</id><link href="https://nguyencungthanh.github.io/tags/heuristic-algorithm/" rel="alternate" type="text/html" title="html"/><link href="https://nguyencungthanh.github.io/tags/heuristic-algorithm/feed.xml" rel="self" type="application/atom+xml" title="atom"/><link href="https://nguyencungthanh.github.io/tags/heuristic-algorithm/feed.json" rel="alternate" type="application/json" title="json"/><updated>2026-10-30T16:35:00+00:00</updated><author><name>Nguyen Cung Thanh</name><email>nguyencungthanh11@gmail.com</email><uri>https://nguyencungthanh.github.io/</uri></author><entry><title type="html">Local Search</title><link href="https://nguyencungthanh.github.io/2026/01/17/local-search/"/><id>https://nguyencungthanh.github.io/2026/01/17/local-search/</id><published>2026-01-17T00:00:00+00:00</published><updated>2026-01-17T00:00:00+00:00</updated><content type="html"><![CDATA[
  <div class='e-content'>
    <p>Given $n$ points in the plane. We want to find a point that minimizes the sum of distance between this point and all of the given points. One of the easiest but efficient way to approach this problem is using <code>Local Search</code>.</p>
<p>Local search is a heuristic method for solving computationally hard optimization problems. Indeed, sometimes we tackle an optimization problem that we cannot find the exactly minimization argument, local search is created to find a &lsquo;good enough&rsquo; solution for the problem. The main ideas of algorithm can be expressed as follow:</p>
<ol>
<li>Initialize an arbitrary configuration</li>
<li>Consider any configuration that adjacents to present configuration and update to the best configuration</li>
<li>Iterate until fixed number of iteration or meet some conditions</li>
</ol>
<p>Back to the initial problem, we can express it as follow:</p>
<div class="post-callout">
Given $n$ points $(x_i,y_i)$ on the plane. Find a point $(x, y)$ that minizes 
$$f(x, y) = \sum_{i = 1}^{n} \sqrt{(x-x_i)^2 + (y-y_i)^2}$$ 
</div>
<p>Taking the partial derivative of $f$ with respect to $x$ and $y$ yields:
$$\begin{cases}
\dfrac{\partial f}{\partial x} = \sum_{i=1}^{n} \dfrac{x-x_i}{\sqrt{(x-x_i)^2 + (y-y_i)^2}} \\
\dfrac{\partial f}{\partial y} = \sum_{i=1}^{n} \dfrac{y-y_i}{\sqrt{(x-x_i)^2 + (y-y_i)^2}}
\end{cases}$$</p>
<p>Set them equal to $0$ we will have
$$x = \dfrac{\sum_{i=1}^{n} w_ix_i}{\sum_{i=1}^n w_i} \quad \text{ and } \quad y = \dfrac{ \sum_{i=1}^{n} w_iy_i}{\sum_{i=1}^n w_i}$$
where $$w_i =  \dfrac{1}{\sqrt{(x-x_i)^2 + (y-y_i)^2}} \quad \forall i = \overline{1,n}$$</p>
<p>This give our idea of update from the k-iteration point $(z_k,w_k)$ to the next point $(z_{k+1}, w_{k+1})$ equal to $$\left(\dfrac{\sum_{i=1}^{n} w_{i,k}x_i}{\sum_{i=1}^n w_{i,k}}, \dfrac{\sum_{i=1}^{n} w_{i,k}x_i}{\sum_{i=1}^n w_{i,k}} \right)$$
with $$w_{i,k} =  \dfrac{1}{\sqrt{(z_k-x_i)^2 + (w_k-y_i)^2}} \quad \forall i = \overline{1,n}$$
Following that idea, we can iterate 100 times and the condition to stop is the distance between the previous point and the new point is less than $10^{-6}$. The below C++ code is the example implementation code for that idea.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">long</span> <span class="kt">double</span>  <span class="nf">distance</span><span class="p">(</span><span class="k">const</span> <span class="n">pair</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span><span class="p">,</span> <span class="kt">long</span> <span class="kt">double</span><span class="o">&gt;&amp;</span> <span class="n">x</span><span class="p">,</span> <span class="k">const</span> <span class="n">pair</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span><span class="p">,</span> <span class="kt">long</span> <span class="kt">double</span><span class="o">&gt;&amp;</span> <span class="n">y</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">    <span class="kt">long</span> <span class="kt">double</span>  <span class="n">result</span> <span class="o">=</span> <span class="n">sqrt</span><span class="p">((</span><span class="n">x</span><span class="p">.</span><span class="n">first</span><span class="o">-</span><span class="n">y</span><span class="p">.</span><span class="n">first</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">first</span><span class="o">-</span><span class="n">y</span><span class="p">.</span><span class="n">first</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">second</span><span class="o">-</span><span class="n">y</span><span class="p">.</span><span class="n">second</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">second</span><span class="o">-</span><span class="n">y</span><span class="p">.</span><span class="n">second</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">pair</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span><span class="p">,</span> <span class="kt">long</span> <span class="kt">double</span><span class="o">&gt;</span> <span class="n">geometric_median</span><span class="p">(</span><span class="k">const</span> <span class="n">vector</span><span class="o">&lt;</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span><span class="p">,</span> <span class="kt">long</span> <span class="kt">double</span><span class="o">&gt;&gt;&amp;</span> <span class="n">points</span><span class="p">,</span> <span class="kt">int</span> <span class="n">max_iteration</span> <span class="o">=</span> <span class="mi">100</span><span class="p">,</span> <span class="kt">long</span> <span class="kt">double</span> <span class="n">tol</span> <span class="o">=</span> <span class="mf">1e-6</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">points</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="kt">long</span> <span class="kt">double</span> <span class="n">sum_x</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="kt">long</span> <span class="kt">double</span> <span class="n">sum_y</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Find the centroid of n points and assign the initial point to the centroid
</span></span></span><span class="line"><span class="cl"><span class="c1"></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="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">        <span class="n">sum_x</span> <span class="o">+=</span> <span class="n">points</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">first</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">sum_y</span> <span class="o">+=</span> <span class="n">points</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">second</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">pair</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span> <span class="p">,</span> <span class="kt">long</span> <span class="kt">double</span> <span class="o">&gt;</span> <span class="n">centroid</span> <span class="o">=</span> <span class="p">{</span><span class="n">sum_x</span><span class="o">/</span><span class="n">n</span><span class="p">,</span> <span class="n">sum_y</span><span class="o">/</span><span class="n">n</span><span class="p">};</span> 
</span></span><span class="line"><span class="cl">    <span class="n">pair</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span> <span class="p">,</span> <span class="kt">long</span> <span class="kt">double</span> <span class="o">&gt;</span> <span class="n">cur_point</span> <span class="o">=</span> <span class="n">centroid</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// lists store the distance and weight between current point and n points
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span> <span class="o">&gt;</span> <span class="n">distances</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span> <span class="o">&gt;</span> <span class="n">weights</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">while</span><span class="p">(</span><span class="n">max_iteration</span><span class="o">--</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">        <span class="kt">bool</span> <span class="n">coincides</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">coincide_idx</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <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="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">distances</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">distance</span><span class="p">(</span><span class="n">cur_point</span><span class="p">,</span> <span class="n">points</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">distances</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="mf">0.0</span><span class="p">)</span> <span class="p">{</span> 
</span></span><span class="line"><span class="cl">                <span class="n">coincides</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">coincide_idx</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">coincides</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">points</span><span class="p">[</span><span class="n">coincide_idx</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <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="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="n">weights</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mf">1.0</span><span class="o">/</span><span class="n">distances</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// Compute new point by the formular: x = (sum w_i*x_i)/(sum w_i), y = (sum w_i*y_i)/(sum w_i)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">long</span> <span class="kt">double</span>  <span class="n">numerator_x</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">,</span> <span class="n">numerator_y</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">,</span> <span class="n">denominator</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <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="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="n">numerator_x</span> <span class="o">+=</span> <span class="n">weights</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">*</span><span class="n">points</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">first</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">numerator_y</span> <span class="o">+=</span> <span class="n">weights</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">*</span><span class="n">points</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">second</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">denominator</span> <span class="o">+=</span> <span class="n">weights</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">pair</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span> <span class="p">,</span> <span class="kt">long</span> <span class="kt">double</span><span class="o">&gt;</span> <span class="n">new_point</span> <span class="o">=</span> <span class="p">{</span><span class="n">numerator_x</span><span class="o">/</span><span class="n">denominator</span><span class="p">,</span> <span class="n">numerator_y</span><span class="o">/</span><span class="n">denominator</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// Compute the distance between new point and current point; if the result is smaller than tolerence then stop the iteration
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">long</span> <span class="kt">double</span>  <span class="n">shift</span> <span class="o">=</span> <span class="n">distance</span><span class="p">(</span><span class="n">new_point</span><span class="p">,</span> <span class="n">cur_point</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="n">shift</span> <span class="o">&lt;</span> <span class="n">tol</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">cur_point</span> <span class="o">=</span> <span class="n">new_point</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">cur_point</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">ios_base</span><span class="o">::</span><span class="n">sync_with_stdio</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">cin</span><span class="p">.</span><span class="n">tie</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="kt">int</span> <span class="n">n</span><span class="p">;</span> <span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">n</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">double</span><span class="p">,</span><span class="kt">long</span> <span class="kt">double</span><span class="o">&gt;&gt;</span> <span class="n">pts</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<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="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">		<span class="kt">long</span> <span class="kt">double</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="n">y</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="n">pts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="k">auto</span> <span class="n">opt</span> <span class="o">=</span> <span class="n">geometric_median</span><span class="p">(</span><span class="n">pts</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">fixed</span> <span class="o">&lt;&lt;</span> <span class="n">setprecision</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Optimal solution&#34;</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;(&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">opt</span><span class="p">.</span><span class="n">first</span> <span class="o">&lt;&lt;</span><span class="s">&#34;, &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">opt</span><span class="p">.</span><span class="n">second</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;)&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>
  </div>
<p>
  <a href="mailto:nguyencungthanh11@gmail.com?subject=Re: Local%20Search" rel='noopener noreferrer'>💬 Reply via e-mail</a>
</p>
]]></content><category term="Heuristic Algorithm"/></entry></feed>