blog/algorithms/paths/bf-to-astar/astar/index.html

104 lines
76 KiB
HTML
Raw Normal View History

<!doctype html>
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-algorithms docs-version-current docs-doc-page docs-doc-id-paths/2024-01-01-bf-to-astar/astar" data-has-hydrated="false">
<head>
<meta charset="UTF-8">
<meta name="generator" content="Docusaurus v3.1.1">
<title data-rh="true">A* algorithm | mf</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://blog.mfocko.xyz/algorithms/paths/bf-to-astar/astar/"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-algorithms-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-algorithms-current"><meta data-rh="true" property="og:title" content="A* algorithm | mf"><meta data-rh="true" name="description" content="Moving from Dijkstra&#x27;s algorithm into the A* algorithm.
"><meta data-rh="true" property="og:description" content="Moving from Dijkstra&#x27;s algorithm into the A* algorithm.
"><link data-rh="true" rel="icon" href="/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://blog.mfocko.xyz/algorithms/paths/bf-to-astar/astar/"><link data-rh="true" rel="alternate" href="https://blog.mfocko.xyz/algorithms/paths/bf-to-astar/astar/" hreflang="en"><link data-rh="true" rel="alternate" href="https://blog.mfocko.xyz/algorithms/paths/bf-to-astar/astar/" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://0VXRFPR4QF-dsn.algolia.net" crossorigin="anonymous"><link rel="search" type="application/opensearchdescription+xml" title="mf" href="/opensearch.xml">
<link rel="alternate" type="application/rss+xml" href="/blog/rss.xml" title="mf RSS Feed">
<link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" title="mf Atom Feed">
<link rel="alternate" type="application/json" href="/blog/feed.json" title="mf JSON Feed">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css" integrity="sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM" crossorigin="anonymous"><link rel="stylesheet" href="/assets/css/styles.e1ac7597.css">
<script src="/assets/js/runtime~main.f2ae61cf.js" defer="defer"></script>
<script src="/assets/js/main.237fcc8a.js" defer="defer"></script>
</head>
<body class="navigation-with-keyboard">
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return localStorage.getItem("theme")}catch(t){}}();t(null!==e?e:"light")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><b class="navbar__title text--truncate">mf</b></a><div class="navbar__item dropdown dropdown--hoverable"><a href="#" aria-haspopup="true" aria-expanded="false" role="button" class="navbar__link">Additional FI MU materials</a><ul class="dropdown__menu"><li><a aria-current="page" class="dropdown__link dropdown__link--active" href="/algorithms/">Algorithms</a></li><li><a class="dropdown__link" href="/c/">C</a></li><li><a class="dropdown__link" href="/cpp/">C++</a></li></ul></div><a class="navbar__item navbar__link" href="/contributions/">Contributions</a><a class="navbar__item navbar__link" href="/talks/">Talks</a></div><div class="navbar__items navbar__items--right"><a class="navbar__item navbar__link" href="/blog/">Blog</a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type="button" disabled="" title="Switch between dark and light mode (currently light mode)" aria-label="Switch between dark and light mode (currently light mode)" aria-live="polite"><svg viewBox="0 0 24 24" width="24" height="24" class="lightToggleIcon_pyhR"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" class="darkToggleIcon_wfgR"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg></button></div><div class="navbarSearchContainer_Bca1"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.
<p>Let&#x27;s start by the recap of what we&#x27;ve achieved so far:</p>
<ol>
<li>We have implemented a naïve brute-force algorithm that tries to relax paths
as long as there are any paths to be relaxed.</li>
<li>Then we have fixed an issue caused by negative loops that can result in
a non-terminating run of our brute-force method. At this moment we have made
some small arguments why are bounding is enough and doesn&#x27;t prevent any
shortest path to <em>not be</em> discovered.</li>
<li>Finally we have converted our bounded brute-force algorithm into the
Bellman-Ford algorithm.</li>
<li>We have mentioned the worst-case time complexity of our bounded naïve
approach and also the Bellman-Ford algorithm. Our worst-case depended on the
fact that we assumed the worst possible ordering of the relaxations. However
we could also try to relax in the most ideal ordering which could result in a
faster algorithm and that&#x27;s how we got to the Dijkstra&#x27;s algorithm.</li>
</ol>
<p>Now the question is, could we improve the Dijkstra&#x27;s algorithm to get even
better results? And the answer is <em>maybe</em>!</p>
<p>Dijkstra&#x27;s algorithm chooses the next cheapest vertex for relaxing. This is good
as long as there is no additional information. However, imagine a roadmap of
some country. If you&#x27;re in the middle of the map and you want to go south, it
doesn&#x27;t make much sense for you to go to the north (in the opposite direction),
but a little bit might make sense, so that you can switch to highway and go much
faster.</p>
<p>The important question here is how to <em>influence</em> the algorithm, so that it does
choose the path that <em>makes more sense</em> rather than the one that costs the
least.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="a-description">A* description<a href="#a-description" class="hash-link" aria-label="Direct link to A* description" title="Direct link to A* description"></a></h2>
<p>The <em>A* algorithm</em> can be considered a modification of Dijkstra&#x27;s algorithm. The
cost is still the same, we cannot change it, right? However when we pick the
vertices from the heap, we can influence the order by some <em>heuristic</em>. In this
case, we introduce a function that can suggest how feasible the vertex is.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="roadmap-heuristic">Roadmap heuristic<a href="#roadmap-heuristic" class="hash-link" aria-label="Direct link to Roadmap heuristic" title="Direct link to Roadmap heuristic"></a></h2>
<p>Let&#x27;s have a look at the heuristic we could use for the roadmap example. There
are roads (the edges) and towns (the vertices). Cost could be an average time to
travel the road. What heuristic could we use to influence our algorithm to
choose a better ordering of the vertices when relaxing?</p>
<p>In the former example we&#x27;ve said that it doesn&#x27;t make much sense to go in the
opposite direction than our goal is… We could choose the distance from our goal
as the heuristic, e.g. right now we&#x27;re 100 km away from our goal, using this
road makes us 50 km away and using the other road we will be 200 km away.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="heuristic-for-our-map">Heuristic for our map<a href="#heuristic-for-our-map" class="hash-link" aria-label="Direct link to Heuristic for our map" title="Direct link to Heuristic for our map"></a></h2>
<p>Our map is a bit simpler, but we can use a very similar principle. We will use
the <em>Manhattan distance</em>, which is defined in a following way:</p>
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal"></mi><msub><mi>x</mi><mi>a</mi></msub><mo></mo><msub><mi>x</mi><mi>b</mi></msub><mi mathvariant="normal"></mi><mo>+</mo><mi mathvariant="normal"></mi><msub><mi>y</mi><mi>a</mi></msub><mo></mo><msub><mi>y</mi><mi>b</mi></msub><mi mathvariant="normal"></mi></mrow><annotation encoding="application/x-tex">\vert x_a - x_b \vert + \vert y_a - y_b \vert</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin"></span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span><span class="mord"></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin"></span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span><span class="mord"></span></span></span></span></span>
<p>Since we cannot move in diagonals, it makes sense to maintain the distance in
the actual steps from the goal.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="passing-the-heuristic">Passing the heuristic<a href="#passing-the-heuristic" class="hash-link" aria-label="Direct link to Passing the heuristic" title="Direct link to Passing the heuristic"></a></h2>
<p>In our case, when we&#x27;re using C++, we can just template the function that will
calculate the shortest path and pass the heuristic as a parameter.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implementation">Implementation<a href="#implementation" class="hash-link" aria-label="Direct link to Implementation" title="Direct link to Implementation"></a></h2>
<p>Actual implementation is very easy once we have the Dijkstra&#x27;s algorithm:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">auto</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">astar</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> graph</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;</span><span class="token plain"> g</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> vertex_t</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;</span><span class="token plain"> source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">auto</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;</span><span class="token plain"> h</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-&gt;</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">vector</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">vector</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// make sure that source exists</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">assert</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">g</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">has</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// initialize the distances</span><span class="token plain"></span><br></span><span class="token
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="running-on-our-map">Running on our map<a href="#running-on-our-map" class="hash-link" aria-label="Direct link to Running on our map" title="Direct link to Running on our map"></a></h2>
<p>For this algorithm I will also show the example of a call:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">distances </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">astar</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">g</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">make_pair</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">9</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">auto</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;</span><span class="token plain"> u</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">auto</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> u</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">abs</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">abs</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="to
<p>First argument to the function is the graph itself. Second argument is the
source vertex where we start. And finally the lambda returns
<em>Manhattan distance</em> to the goal.</p>
<p>And we get the following result:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Normal cost: 1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Vortex cost: 5</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Graph:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#############</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#..*.*.**#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">##***.....**#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..########.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#...###...#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#...##.#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#.*.#..#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#D...#....#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">########*.*.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#S..........#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#############</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Finite BF] Cost: 22</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Bellman-Ford] Cost: 22</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Dijkstra] Cost: 22</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[A*] Cost: 22</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="comparison">Comparison<a href="#comparison" class="hash-link" aria-label="Direct link to Comparison" title="Direct link to Comparison"></a></h2>
<p>Now you may wonder how does it compare to the previous algorithms. Supposedly it
should be faster. Let&#x27;s add counters and debugging output when we update
distance to our goal. And now if we run our code, we get the following output:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Normal cost: 1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Vortex cost: 5</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Graph:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#############</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#..*.*.**#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">##***.....**#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..########.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#...###...#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#...##.#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#.*.#..#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#D...#....#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">########*.*.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#S..........#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#############</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Relaxing path to goal in 40. relaxation</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Relaxing path to goal in 68. relaxation</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Relaxing path to goal in 89. relaxation</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Finite BF] Cost: 22</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Relaxing path to goal in 40. relaxation</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Relaxing path to goal in 68. relaxation</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Relaxing path to goal in 89. relaxation</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Bellman-Ford] Cost: 22</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Relaxing path to goal in 41. iteration</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Dijkstra] Cost: 22</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Relaxing path to goal in 31. iteration</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[A*] Cost: 22</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></
<p>From the output we can easily deduce that for both brute-force and Bellman-Ford,
which are in our case identical, we actually relax three times and for the last
time in the 89th iteration.</p>
<p>Dijkstra&#x27;s algorithm manages to find the shortest path to our goal already in
the 41st iteration.</p>
<p>And finally after introducing some heuristic, we could find the shortest path
in the 31st iteration.</p>
<div class="theme-admonition theme-admonition-danger admonition_xJq3 alert alert--danger"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>danger</div><div class="admonitionContent_BuS1"><p>Please keep in mind that choosing bad heuristic can actually lead to worse
results than using no heuristic at all.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a href="#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary"></a></h2>
<p>And there we have it. We have made our way from the brute-force algorithm all
the way to more optimal ones. Hopefully we could notice how the small
improvements of the already existing algorithms made them much better.</p></div><footer class="theme-doc-footer docusaurus-mt-lg"><div class="theme-doc-footer-tags-row row margin-bottom--sm"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/algorithms/tags/cpp/">cpp</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/algorithms/tags/dynamic-programming/">dynamic programming</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/algorithms/tags/astar/">astar</a></li></ul></div></div><div class="theme-doc-footer-edit-meta-row row"><div class="col"><a href="https://github.com/mfocko/blog/tree/main/algorithms/11-paths/2024-01-01-bf-to-astar/03-astar.md" target="_blank" rel="noopener noreferrer" class="theme-edit-this-page"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_Z9Sw" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col lastUpdated_vwxv"><span class="theme-last-updated">Last updated<!-- --> on <b><time datetime="2024-01-03T00:00:00.000Z">Jan 3, 2024</time></b></span></div></div></footer></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="/algorithms/paths/bf-to-astar/dijkstra/"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">Dijkstra&#x27;s algorithm</div></a><a class="pagination-nav__link pagination-nav__link--next" href="/algorithms/category/hash-tables/"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Hash Tables</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#intro" class="table-of-contents__link toc-highlight">Intro</a></li><li><a href="#a-description" class="table-of-contents__link toc-highlight">A* description</a></li><li><a href="#roadmap-heuristic" class="table-of-contents__link toc-highlight">Roadmap heuristic</a></li><li><a href="#heuristic-for-our-map" class="table-of-contents__link toc-highlight">Heuristic for our map</a></li><li><a href="#passing-the-heuristic" class="table-of-contents__link toc-highlight">Passing the heuristic</a></li><li><a href="#implementation" class="table-of-contents__link toc-highlight">Implementation</a></li><li><a href="#running-on-our-map" class="table-of-contents__link toc-highlight">Running on our map</a></li><li><a href="#comparison" class="table-of-contents__link toc-highlight">Comparison</a></li><li><a href="#summary" class="table-of-contents__link toc-highlight">Summary</a></li></ul></div></div></div></div></main></div></div></div><footer class="footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="col footer__col"><div class="footer__title">Git</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://github.com/mfocko" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://gitlab.com/mfocko" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitLab<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://git.mfocko.xyz/mfocko" target="_blank" rel="noopener noreferrer"
</body>
</html>