<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kyrylo Malovychko</title>
    <description>The latest articles on DEV Community by Kyrylo Malovychko (@katalvlaran).</description>
    <link>https://dev.to/katalvlaran</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4053267%2F5adf3411-15c1-47b3-b8c5-232a5c41e64a.jpg</url>
      <title>DEV Community: Kyrylo Malovychko</title>
      <link>https://dev.to/katalvlaran</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/katalvlaran"/>
    <language>en</language>
    <item>
      <title>The Best DTW Candidate Scored 9.97. That Still Wasn't a Decision...</title>
      <dc:creator>Kyrylo Malovychko</dc:creator>
      <pubDate>Tue, 01 Sep 2026 15:38:14 +0000</pubDate>
      <link>https://dev.to/katalvlaran/the-best-dtw-candidate-scored-997-that-still-wasnt-a-decision-g5a</link>
      <guid>https://dev.to/katalvlaran/the-best-dtw-candidate-scored-997-that-still-wasnt-a-decision-g5a</guid>
      <description>&lt;p&gt;I pointed a DTW scanner at the official Binance Spot &lt;code&gt;ETHUSDT&lt;/code&gt; one-minute archive for July 2023.&lt;/p&gt;

&lt;p&gt;The reference window was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2023-07-01 12:13–12:23 UTC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The best non-overlapping candidate in the monthly scan was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2023-07-27 17:45–17:55 UTC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scanner returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;distance=9.967796
path-steps=11
stretch-steps=2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fine.&lt;/p&gt;

&lt;p&gt;Is that a match?&lt;/p&gt;

&lt;p&gt;No honest answer yet.&lt;/p&gt;

&lt;p&gt;It is the smallest distance found under one preprocessing rule, one local cost, one Sakoe–Chiba window, and one slope penalty. The scanner found an &lt;code&gt;argmin&lt;/code&gt;. It did not magically produce a trading decision.&lt;/p&gt;

&lt;p&gt;That distinction is where most DTW demos stop being useful.&lt;/p&gt;

&lt;p&gt;I also tried to use two Binance UI screenshots as provenance. I rejected them.&lt;/p&gt;

&lt;p&gt;The visible price scales did not match the CSV rows used by the scanner: the reference file contains roughly &lt;code&gt;1925–1927&lt;/code&gt;, while the screenshot showed a different price region; the candidate file contains roughly &lt;code&gt;1864–1867&lt;/code&gt;, while its screenshot was around &lt;code&gt;1923–1929&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Wrong date, wrong market, wrong timezone, or a chart that never actually jumped to the requested archive — it does not matter. A pretty screenshot pointing at different candles is worse than no screenshot.&lt;/p&gt;

&lt;p&gt;The figure below is rebuilt directly from the exact OHLC rows fed into the scan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftucpqz7p054puf8atuwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftucpqz7p054puf8atuwg.png" alt="The exact 11-candle Binance windows used by the scanner" width="799" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

The two selected windows reconstructed from the exported Binance kline rows. Their nominal price levels differ, so the alignment model uses return shape rather than raw-price equality.




&lt;h2&gt;
  
  
  The score got four times smaller. It still did not become a probability.
&lt;/h2&gt;

&lt;p&gt;The two windows live at different nominal price levels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reference: around 1,926 USDT
candidate: around 1,865 USDT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comparing raw closes would mostly measure that price-level difference. The scanner converts each window to close-to-close returns in basis points:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;returnBPS&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;currentClose&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;previousClose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;previousClose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That transformation is visible in the code. &lt;code&gt;lvlath/dtw&lt;/code&gt; does not silently normalize the sequence behind the caller's back.&lt;/p&gt;

&lt;p&gt;Hidden normalization is the sort of “help” that makes a demo look clean and a production incident miserable to reconstruct.&lt;/p&gt;

&lt;p&gt;With strict index pairing, the ten return samples accumulate an absolute cost of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;39.893841
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The selected DTW path accumulates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;9.967796
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;under the same absolute local cost and a &lt;code&gt;0.05&lt;/code&gt; penalty for every horizontal or vertical move.&lt;/p&gt;

&lt;p&gt;The objective fell by roughly 75%.&lt;/p&gt;

&lt;p&gt;That is &lt;strong&gt;not&lt;/strong&gt; a 75% similarity score. It only says that allowing a constrained time deformation explains the two return sequences much better than forcing sample &lt;code&gt;i&lt;/code&gt; to match sample &lt;code&gt;i&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozmna8odywzv6z80gwvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozmna8odywzv6z80gwvz.png" alt="The exact return series and the selected DTW path" width="799" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

The actual model input. Left: close-to-close returns in basis points. Right: the local absolute-cost surface and selected path.




&lt;p&gt;A percentage without calibration is just a confident UI element.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the real path says
&lt;/h2&gt;

&lt;p&gt;The scanner called:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;dtw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Align&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidateSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;referenceSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The public coordinate contract is therefore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Coord.I → candidate index
Coord.J → reference index
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The selected path was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{0,0}
{0,1}   horizontal
{1,2}
{2,3}
{3,4}
{4,5}
{5,6}
{6,7}
{7,8}
{8,9}
{9,9}   vertical
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of the path runs diagonally with a one-step offset.&lt;/p&gt;

&lt;p&gt;Two cells carry the temporal deformation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{0,0} → {0,1}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The candidate's first return is held while the reference advances once.&lt;/p&gt;

&lt;p&gt;At the other end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{8,9} → {9,9}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The candidate advances while the final reference phase is held.&lt;/p&gt;

&lt;p&gt;That is much more useful than “9.97”. It tells the reviewer exactly where the clocks were stretched.&lt;/p&gt;

&lt;p&gt;The path also shows what DTW did &lt;strong&gt;not&lt;/strong&gt; fix. The largest local contribution on the selected route is &lt;code&gt;3.578995&lt;/code&gt;, where candidate return &lt;code&gt;-3.321707&lt;/code&gt; is paired with reference return &lt;code&gt;-6.900703&lt;/code&gt;. Warping can move time; it cannot turn a genuinely different price move into the same move.&lt;/p&gt;

&lt;p&gt;This is why a warping path is evidence, not a permission slip.&lt;/p&gt;

&lt;h2&gt;
  
  
  “Best candidate” is not “accepted match”
&lt;/h2&gt;

&lt;p&gt;The first scanner version printed only the minimum.&lt;/p&gt;

&lt;p&gt;That is enough for ranking, not classification.&lt;/p&gt;

&lt;p&gt;Suppose the best monthly distance is &lt;code&gt;9.967796&lt;/code&gt;. Is that excellent, mediocre, or awful?&lt;/p&gt;

&lt;p&gt;The answer needs context the DTW recurrence does not own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a labeled positive/negative corpus;&lt;/li&gt;
&lt;li&gt;a threshold selected against false-positive and false-negative cost;&lt;/li&gt;
&lt;li&gt;distance distributions for the same preprocessing and policy;&lt;/li&gt;
&lt;li&gt;perhaps a second-stage rule that inspects path shape, stretch count, or domain constraints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A threshold copied from a synthetic fixture would be especially bad. The deterministic repository example reports &lt;code&gt;0.89&lt;/code&gt;; that does not make &lt;code&gt;1.50&lt;/code&gt; a valid production cutoff for this Binance corpus.&lt;/p&gt;

&lt;p&gt;A cutoff from the synthetic fixture does not survive a change of data distribution.&lt;/p&gt;

&lt;p&gt;The updated article scanner therefore uses two passes and can export every candidate score.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg4mww4jxyn67yxukbl3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg4mww4jxyn67yxukbl3d.png" alt="Two-pass DTW service architecture" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

Scan every candidate with rolling rows. Recover a path only for the shortlist. Keep the business threshold outside the alignment kernel.




&lt;p&gt;The architecture is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. preprocess explicitly
2. scan every window distance-only
3. rank / apply a calibrated threshold
4. rerun selected windows with path tracking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No need to allocate an &lt;code&gt;O(n×m)&lt;/code&gt; backtracking surface for every candidate and then act surprised when the pod gets &lt;code&gt;OOMKilled&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The current &lt;code&gt;lvlath/dtw&lt;/code&gt; API
&lt;/h2&gt;

&lt;p&gt;The package exposes three canonical facades because “time series” is not one data type.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Align&lt;/code&gt;: scalar sequences
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;Align&lt;/code&gt; when one scalar represents one time step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;dtw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Align&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;candidateReturns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;referenceReturns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;dtw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;dtw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithSlopePenalty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default local cost is absolute difference. Callers can select squared cost or provide a deterministic custom &lt;code&gt;CostFunc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This surface fits returns, temperatures, single-axis sensors, latency traces, or other scalar signals.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;AlignMatrix&lt;/code&gt;: multivariate features
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;AlignMatrix&lt;/code&gt; when each time step has several features:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;dtw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;breakoutTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;liveWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;dtw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;dtw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithSlopePenalty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;dtw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithReturnPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rows are time steps. Columns are features. The two matrices must have the same feature dimension.&lt;/p&gt;

&lt;p&gt;The facade builds pairwise local costs with squared L2 distance between rows.&lt;/p&gt;

&lt;p&gt;It does not normalize the features.&lt;/p&gt;

&lt;p&gt;Leaving preprocessing to the caller is an ownership decision.&lt;/p&gt;

&lt;p&gt;OHLC, returns, z-scores, volatility-adjusted values, sensor channels, and embeddings are different mathematical inputs. A library that silently rescales them has changed the problem while pretending to save the caller a few lines.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;AlignCostMatrix&lt;/code&gt;: bring your own local model
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;AlignCostMatrix&lt;/code&gt; when another system already produced the &lt;code&gt;n×m&lt;/code&gt; pairwise cost surface.&lt;/p&gt;

&lt;p&gt;The voice-command example feeds a &lt;code&gt;10×14&lt;/code&gt; acoustic local-cost matrix. An embedding model, phoneme recognizer, frame matcher, or domain-specific rule engine could own the same layer.&lt;/p&gt;

&lt;p&gt;DTW then does one job: find the cheapest admissible monotone path through that surface.&lt;/p&gt;

&lt;p&gt;The local costs still have a contract. They must be finite and non-negative.&lt;/p&gt;

&lt;h2&gt;
  
  
  Window and slope are not decorative tuning knobs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The window
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;WithWindow(w)&lt;/code&gt; defines the Sakoe–Chiba band:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;w = -1   no band constraint
w =  0   strict diagonal
w &amp;gt;= 0   only cells with |i-j| &amp;lt;= w
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;0&lt;/code&gt; does not mean “disabled”. It means no temporal deformation at all.&lt;/p&gt;

&lt;p&gt;A finite band blocks ridiculous alignments: the first phoneme should not match the end of a command; the onset of a vibration event should not match recovery.&lt;/p&gt;

&lt;p&gt;The policy can also make alignment impossible. If the band contains no valid path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reachable=false
Distance=+Inf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a legitimate model result, not a panic.&lt;/p&gt;

&lt;h3&gt;
  
  
  The slope penalty
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;WithSlopePenalty(p)&lt;/code&gt; adds &lt;code&gt;p&lt;/code&gt; only to horizontal and vertical steps.&lt;/p&gt;

&lt;p&gt;Those are exactly the moves that hold one sequence while the other advances.&lt;/p&gt;

&lt;p&gt;A positive penalty makes temporal stretching cost something. Zero leaves it free except for local mismatch.&lt;/p&gt;

&lt;p&gt;Neither choice is universally correct.&lt;/p&gt;

&lt;p&gt;A voice command may tolerate a held vowel. A machinery signature may treat an extra peak frame as suspicious. A market scanner may allow a one- or two-candle delay but reject a pattern smeared across half an hour.&lt;/p&gt;

&lt;p&gt;The number belongs to the domain, not to DTW folklore.&lt;/p&gt;

&lt;h2&gt;
  
  
  The path is deterministic on purpose
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;lvlath/dtw&lt;/code&gt; returns one deterministic representative optimal path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Coord&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;J&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Coord&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Several predecessor cells can have equal accumulated cost. The package uses a fixed backtracking order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;diagonal
then vertical/up
then horizontal/left
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does not claim the mathematical optimum is unique.&lt;/p&gt;

&lt;p&gt;It means a stable distance also produces a stable explanation.&lt;/p&gt;

&lt;p&gt;That matters when tests assert phase anchors, incident reports compare paths, or downstream logic counts stretch steps. Without a tie-break law, an internal refactor can leave the scalar unchanged and quietly rewrite the witness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask for a path and the bill changes. It should.
&lt;/h2&gt;

&lt;p&gt;The benchmark suite measures separate DTW contracts rather than pretending they are one workload.&lt;/p&gt;

&lt;p&gt;On this machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;darwin/amd64
Intel Core i9-9880H @ 2.30GHz
10 benchmark runs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The saved output did not include &lt;code&gt;go version&lt;/code&gt;. Add the actual toolchain before publication; guessing it later would undermine the reproduction block.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;benchstat&lt;/code&gt; reported:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Contract&lt;/th&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th&gt;Time/op&lt;/th&gt;
&lt;th&gt;B/op&lt;/th&gt;
&lt;th&gt;allocs/op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scalar distance, &lt;code&gt;TwoRows&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;500×500&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.169 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8.156 KiB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reachable band, &lt;code&gt;w=10&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;500×500&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;527.8 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8.156 KiB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strict-diagonal no path, &lt;code&gt;w=0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;500×501&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;455.0 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8.156 KiB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;FullMatrix&lt;/code&gt; + path&lt;/td&gt;
&lt;td&gt;&lt;code&gt;250×250&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.232 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1004.2 KiB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;AlignMatrix&lt;/code&gt;, squared L2, &lt;code&gt;d=8&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;200×200&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.935 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1007.3 KiB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is not a speed ranking. The dimensions and returned artifacts differ.&lt;/p&gt;

&lt;p&gt;It does expose three useful facts.&lt;/p&gt;

&lt;p&gt;First, the finite &lt;code&gt;w=10&lt;/code&gt; band ran about &lt;code&gt;4.1×&lt;/code&gt; faster than unconstrained scalar &lt;code&gt;500×500&lt;/code&gt; distance on this fixture while keeping the same rolling-row allocation profile.&lt;/p&gt;

&lt;p&gt;Second, the smaller &lt;code&gt;250×250&lt;/code&gt; path workload allocated roughly &lt;code&gt;123×&lt;/code&gt; more bytes per operation than scalar &lt;code&gt;500×500&lt;/code&gt; distance-only mode.&lt;/p&gt;

&lt;p&gt;That is the cost of retaining accumulated state and recovering a witness. The lower runtime is not a contradiction; the path benchmark has only one quarter as many grid cells.&lt;/p&gt;

&lt;p&gt;Third, &lt;code&gt;AlignMatrix&lt;/code&gt; also sits around one megabyte per operation at &lt;code&gt;200×200×8&lt;/code&gt; because the facade materializes the multivariate local-cost surface.&lt;/p&gt;

&lt;p&gt;So the honest memory statement is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DTW uses O(m) memory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Scalar distance-only &lt;code&gt;Align&lt;/code&gt; can keep accumulated DP state in O(m). Path recovery needs O(n×m), and &lt;code&gt;AlignMatrix&lt;/code&gt; has an additional O(n×m) local-cost surface.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2gz8r1w83yp0ih3lw79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2gz8r1w83yp0ih3lw79.png" alt="Measured DTW result contracts" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

Different workloads, different artifacts. The table is not a universal solver ranking; it exposes the resource contract of each mode.




&lt;h2&gt;
  
  
  Returning &lt;code&gt;nil&lt;/code&gt; and making the caller play detective is lazy API design
&lt;/h2&gt;

&lt;p&gt;The result carries the state needed to interpret it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Distance&lt;/span&gt;  &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;Reachable&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;

    &lt;span class="n"&gt;Path&lt;/span&gt;        &lt;span class="n"&gt;Path&lt;/span&gt;
    &lt;span class="n"&gt;PathTracked&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;

    &lt;span class="n"&gt;Window&lt;/span&gt;       &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;SlopePenalty&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;MemoryMode&lt;/span&gt;   &lt;span class="n"&gt;MemoryMode&lt;/span&gt;

    &lt;span class="n"&gt;Accumulated&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dense&lt;/span&gt;
    &lt;span class="n"&gt;LocalCost&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dense&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PathOrError()&lt;/code&gt; distinguishes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nil result
    → ErrNilResult

no admissible alignment
    → ErrNoPath

finite alignment, path not requested
    → ErrPathNotTracked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A distance-only scan is a successful operation. It should not look like an alignment failure merely because no path slice was allocated.&lt;/p&gt;

&lt;p&gt;A too-tight window is a different outcome. Caller logic may widen the band, reject the candidate, or record a policy failure.&lt;/p&gt;

&lt;p&gt;Different decisions deserve different states.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crypto is only one workload
&lt;/h2&gt;

&lt;p&gt;The same result model appears in two other runnable examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voice command
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;distance=0.83
path-steps=14
stretch-steps=4
decision=accepted with stretched pronunciation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The local acoustic-cost surface is computed elsewhere; &lt;code&gt;AlignCostMatrix&lt;/code&gt; recovers the monotone correspondence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vibration signature
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;distance=0.0776
path-steps=17
stretch-steps=3
peak={6,8}
decision=signature match
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;AlignMatrix&lt;/code&gt; compares three sensor features per time step and accepts a delayed-but-normal spindle impact.&lt;/p&gt;

&lt;p&gt;Other plausible uses follow the same shape:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gesture and motion alignment;&lt;/li&gt;
&lt;li&gt;production-cycle timing;&lt;/li&gt;
&lt;li&gt;latency-profile comparison;&lt;/li&gt;
&lt;li&gt;ECG or respiratory phase alignment;&lt;/li&gt;
&lt;li&gt;video-frame or embedding correspondence;&lt;/li&gt;
&lt;li&gt;event-sequence template matching.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The API does not make those domains equivalent. It gives each one the same honest set of artifacts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;distance
path
local cost
accumulated cost
reachability
memory policy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reproduce the real-data scan
&lt;/h2&gt;

&lt;p&gt;The source dataset is the official Binance Spot monthly kline archive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ETHUSDT
1-minute candles
July 2023
UTC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The article package includes the exact selected windows, path CSV, screenshots, and an updated two-pass scanner.&lt;/p&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run ./dtw_binance_real_scan_v2.go &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-csv&lt;/span&gt; ETHUSDT-1m-2023-07.csv &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-reference-start&lt;/span&gt; 2023-07-01T12:13:00Z &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-candles&lt;/span&gt; 11 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-window&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-slope&lt;/span&gt; 0.05 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-exclude&lt;/span&gt; 30 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-top&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out-prefix&lt;/span&gt; ethusdt-dtw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scanner deliberately prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;classification=not-configured
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;until the caller supplies a calibrated threshold.&lt;/p&gt;

&lt;p&gt;That line is not missing functionality. It prevents the monthly &lt;code&gt;argmin&lt;/code&gt; from being smuggled into business logic as a verified pattern match.&lt;/p&gt;

&lt;h2&gt;
  
  
  The useful boundary
&lt;/h2&gt;

&lt;p&gt;A distance answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which candidate is closest under this preprocessing and policy?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A path answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which time steps correspond, and where did the clock stretch?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A local-cost matrix answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which feature pairs created the mismatch?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An accumulated matrix answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why did dynamic programming choose this route through the cost surface?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A threshold answers another question entirely:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this candidate good enough for my application?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One float should not pretend to answer all five.&lt;/p&gt;




&lt;h2&gt;
  
  
  Source and reproduction material
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Package: &lt;a href="https://github.com/lvlath/go/tree/main/dtw" rel="noopener noreferrer"&gt;https://github.com/lvlath/go/tree/main/dtw&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go Reference: &lt;a href="https://pkg.go.dev/github.com/lvlath/go@v0.1.0/dtw" rel="noopener noreferrer"&gt;https://pkg.go.dev/github.com/lvlath/go@v0.1.0/dtw&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Current API: &lt;a href="https://github.com/lvlath/go/blob/main/dtw/api.go" rel="noopener noreferrer"&gt;https://github.com/lvlath/go/blob/main/dtw/api.go&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Current options: &lt;a href="https://github.com/lvlath/go/blob/main/dtw/options.go" rel="noopener noreferrer"&gt;https://github.com/lvlath/go/blob/main/dtw/options.go&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Current result types: &lt;a href="https://github.com/lvlath/go/blob/main/dtw/types.go" rel="noopener noreferrer"&gt;https://github.com/lvlath/go/blob/main/dtw/types.go&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Runnable examples: &lt;a href="https://github.com/lvlath/go/blob/main/dtw/example_test.go" rel="noopener noreferrer"&gt;https://github.com/lvlath/go/blob/main/dtw/example_test.go&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Deterministic long-stream scanner: &lt;a href="https://github.com/lvlath/go/blob/main/examples/dtw_signal_alignment.go" rel="noopener noreferrer"&gt;https://github.com/lvlath/go/blob/main/examples/dtw_signal_alignment.go&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Playground: &lt;a href="https://go.dev/play/p/96eGjJQxauW" rel="noopener noreferrer"&gt;https://go.dev/play/p/96eGjJQxauW&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Benchmarks: &lt;a href="https://github.com/lvlath/go/blob/main/dtw/bench_test.go" rel="noopener noreferrer"&gt;https://github.com/lvlath/go/blob/main/dtw/bench_test.go&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>algorithms</category>
      <category>opensource</category>
      <category>lvlath</category>
    </item>
    <item>
      <title>Three Correct TSP Solvers. Three Incompatible Promises.</title>
      <dc:creator>Kyrylo Malovychko</dc:creator>
      <pubDate>Thu, 13 Aug 2026 12:02:46 +0000</pubDate>
      <link>https://dev.to/katalvlaran/three-correct-tsp-solvers-three-incompatible-promises-4d2h</link>
      <guid>https://dev.to/katalvlaran/three-correct-tsp-solvers-three-incompatible-promises-4d2h</guid>
      <description>&lt;p&gt;The cold-chain fixture returns a &lt;strong&gt;114-minute&lt;/strong&gt; tour. The validated thermal window is &lt;strong&gt;120 minutes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Six minutes of margin.&lt;/p&gt;

&lt;p&gt;The dispatcher asks a perfectly reasonable question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is 114 the best possible route?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this run, the answer is &lt;strong&gt;not proven&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The tour came from Christofides with exact minimum-weight perfect matching. &lt;code&gt;lvlath/tsp&lt;/code&gt; publishes &lt;code&gt;ApproximationRatio=1.5&lt;/code&gt; and &lt;code&gt;Optimal=false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The difference matters because the public call looks identical.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Tour&lt;/code&gt; and &lt;code&gt;Cost&lt;/code&gt; are not enough for a production TSP result. In a 30-matrix experiment, 2-opt matched the exact optimum cost &lt;strong&gt;24/30&lt;/strong&gt; times and 3-opt &lt;strong&gt;27/30&lt;/strong&gt; times, yet neither solver can honestly publish &lt;code&gt;Optimal=true&lt;/code&gt;. Christofides + Blossom matched the optimum only &lt;strong&gt;8/30&lt;/strong&gt; times, but it is the heuristic regime with a formal &lt;code&gt;1.5&lt;/code&gt; worst-case guarantee. Runtime, observed solution quality, and proof strength are different axes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Textbooks explain permutations, NP-hardness, Branch-and-Bound, and 2-opt well enough. The awkward part appears later, when all of those algorithms are hidden behind one friendly function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The call looks uniform. The result is not.&lt;/p&gt;
&lt;h2&gt;
  
  
  One result type, several very different claims
&lt;/h2&gt;

&lt;p&gt;This is the public &lt;code&gt;Result&lt;/code&gt; in &lt;code&gt;github.com/lvlath/go@v0.1.0/tsp&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Tour&lt;/span&gt;  &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Cost&lt;/span&gt;  &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;IDs&lt;/span&gt;   &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;

    &lt;span class="n"&gt;Algorithm&lt;/span&gt; &lt;span class="n"&gt;Algorithm&lt;/span&gt;
    &lt;span class="n"&gt;Exact&lt;/span&gt;     &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;Optimal&lt;/span&gt;   &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;TimedOut&lt;/span&gt;  &lt;span class="kt"&gt;bool&lt;/span&gt;

    &lt;span class="n"&gt;MetricClosureApplied&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;Symmetric&lt;/span&gt;             &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;ApproximationRatio&lt;/span&gt;   &lt;span class="kt"&gt;float64&lt;/span&gt;

    &lt;span class="n"&gt;Iterations&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;NodesExpanded&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Those fields are intentionally redundant with the solver choice. A caller should not have to reconstruct what happened from old options, log text, or a function name.&lt;/p&gt;

&lt;p&gt;A few valid states:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Exact&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Optimal&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;TimedOut&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;ApproximationRatio&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Held-Karp completed&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch-and-Bound completed&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch-and-Bound stopped by time limit&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Blossom&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Greedy&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2-opt / 3-opt&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Route one: six minutes of cold-chain margin
&lt;/h2&gt;

&lt;p&gt;The first runnable example is a six-stop symmetric metric travel-time matrix for vaccine distribution.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Algo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Christofides&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Symmetric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartVertex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchingAlgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BlossomMatch&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableLocalSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The relevant output is short:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;route-minutes=114.0
formal-ratio=1.5
thermal-margin=6.0 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;114&lt;/code&gt; is empirical: it belongs to this matrix and this returned tour.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;1.5&lt;/code&gt; comes from a theorem, and it survives only if the whole Christofides contract survives.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhrtqon2hetoxf1g5lkgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhrtqon2hetoxf1g5lkgw.png" alt=" " width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;
Same outer pipeline, different matching policy. The proof obligation changes even when both paths return a valid tour.



&lt;p&gt;One caveat matters here: &lt;code&gt;v0.1.0&lt;/code&gt; documents &lt;strong&gt;metric input as a precondition&lt;/strong&gt;; it does not prove the triangle inequality for every arbitrary matrix before solving. Symmetry and completeness can be validated mechanically. Metricity may still be a domain fact the caller has to defend. If that assumption is not trustworthy, the downstream system should not present &lt;code&gt;1.5&lt;/code&gt; as an unconditional theorem.&lt;/p&gt;

&lt;p&gt;The load-bearing stage here is minimum-weight perfect matching on the odd-degree vertices of the MST.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lvlath/tsp&lt;/code&gt; exposes that choice directly:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;GreedyMatch&lt;/span&gt; &lt;span class="n"&gt;MatchingAlgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;
    &lt;span class="n"&gt;BlossomMatch&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;BlossomMatch&lt;/code&gt; is exact MWPM. &lt;code&gt;GreedyMatch&lt;/code&gt; is deterministic and cheaper, but heuristic.&lt;/p&gt;

&lt;p&gt;So this is a valid explicit configuration:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Algo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Christofides&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Symmetric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchingAlgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GreedyMatch&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableLocalSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApproximationRatio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 0: no formal ratio claimed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There is no hidden "Blossom failed, quietly use Greedy" fallback. A failed stronger policy stays visible instead of returning weaker mathematics with stronger-looking metadata.&lt;/p&gt;
&lt;h2&gt;
  
  
  Route two: asymmetric cost is domain information
&lt;/h2&gt;

&lt;p&gt;The second example models armored cash-in-transit routing. Cost combines time, fuel, guard exposure, and interception risk, so &lt;code&gt;A -&amp;gt; B&lt;/code&gt; can legitimately differ from &lt;code&gt;B -&amp;gt; A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The solver is directed 2-opt*:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Algo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TwoOptOnly&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Symmetric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartVertex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableLocalSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It returns:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;directed-risk-cost=34.0
exact=false
optimal=false
approximation-ratio=0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The result is a deterministic locally improved ATSP tour under the selected policy. &lt;code&gt;ApproximationRatio=0&lt;/code&gt; states the missing guarantee explicitly instead of leaving the caller to infer it from &lt;code&gt;Algorithm&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Route three: exact search can still return a non-optimal result
&lt;/h2&gt;

&lt;p&gt;The semiconductor example has five drilling sites and an offline planning stage, so Branch-and-Bound with a 1-tree lower bound is a sensible exact choice:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Algo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BranchAndBound&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Symmetric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartVertex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BoundAlgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OneTreeBound&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableLocalSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The example completes with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;single-board-latency=16.8 ms
exact=true
optimal=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now add a wall-clock limit.&lt;/p&gt;

&lt;p&gt;Branch-and-Bound is still an exact algorithm, but an interrupted search has not completed the proof. &lt;code&gt;v0.1.0&lt;/code&gt; may return a non-nil incumbent together with &lt;code&gt;ErrTimeLimit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrTimeLimit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"time limit without incumbent"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cost=%.3f exact=%v optimal=%v timedOut=%v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c"&gt;// true&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Optimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c"&gt;// false&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimedOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// true&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Exact&lt;/code&gt; describes the algorithm family. &lt;code&gt;Optimal&lt;/code&gt; describes what this invocation actually proved.&lt;/p&gt;

&lt;p&gt;That is a distinction a single &lt;code&gt;Success bool&lt;/code&gt; cannot encode.&lt;/p&gt;
&lt;h2&gt;
  
  
  180 runs: observed quality vs. formal proof
&lt;/h2&gt;

&lt;p&gt;For the article I generated &lt;strong&gt;30 deterministic Euclidean metric matrices&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n = 8, 10, 12
10 fixed seeds per size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Each matrix was solved by six policies, for &lt;strong&gt;180 solver runs&lt;/strong&gt;. Held-Karp supplied the exact-cost baseline. Before writing a CSV row, an independent harness checked that the returned witness was a closed Hamiltonian cycle, visited every matrix vertex once, used finite non-negative edges, and recomputed the published cost from the source matrix.&lt;/p&gt;

&lt;p&gt;I kept solution-quality measurements separate from &lt;code&gt;testing.B&lt;/code&gt;: &lt;code&gt;duration_ns&lt;/code&gt; in that CSV is diagnostic single-run timing, not benchmark evidence.&lt;/p&gt;

&lt;p&gt;Across all 30 matrices:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solver&lt;/th&gt;
&lt;th&gt;Median gap to exact&lt;/th&gt;
&lt;th&gt;Worst observed gap&lt;/th&gt;
&lt;th&gt;Matched exact cost&lt;/th&gt;
&lt;th&gt;What that proves&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Held-Karp&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;30 / 30&lt;/td&gt;
&lt;td&gt;exact baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch-and-Bound&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;30 / 30&lt;/td&gt;
&lt;td&gt;completed exact search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Blossom&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.059%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;12.234%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8/30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;empirical quality + formal 1.5 bound&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Greedy&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8.261%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;34.568%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5/30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;empirical quality only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2-opt&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.634%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;24/30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;empirical quality only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3-opt&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.222%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;27/30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;empirical quality only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51csu9jnt4kj4kmyri2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51csu9jnt4kj4kmyri2f.png" alt=" " width="799" height="462"&gt;&lt;/a&gt;&lt;/p&gt;
Local search won the empirical hit-rate on these small fixtures; Christofides + Blossom retained the theorem.



&lt;p&gt;This is where the experiment gets uncomfortable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2-opt hit the exact optimum cost 24 times. Christofides + Blossom did it 8 times. Yet Christofides is the one allowed to publish a worst-case mathematical guarantee.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The apparent contradiction disappears once the two questions are separated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;How did this solver behave on these 30 fixtures?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;What can the algorithm prove outside this sample?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first is empirical evidence. The second is a theorem.&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  &lt;br&gt;
&lt;strong&gt;Observed quality and proof strength are different axes.&lt;/strong&gt;&lt;br&gt;

&lt;/div&gt;



&lt;p&gt;Treating "the route was close to the optimum in my benchmark" as a formal guarantee is benchmark-driven overfitting.&lt;/p&gt;

&lt;h3&gt;
  
  
  One matrix makes the distinction even sharper
&lt;/h3&gt;

&lt;p&gt;The equal-size benchmark used the same deterministic &lt;code&gt;n=10&lt;/code&gt;, seed-47 matrix for every solver. &lt;code&gt;testing.B&lt;/code&gt; measured only &lt;code&gt;SolveMatrix&lt;/code&gt;; fixture construction stayed outside the timed region.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solver&lt;/th&gt;
&lt;th&gt;Median time&lt;/th&gt;
&lt;th&gt;B/op&lt;/th&gt;
&lt;th&gt;allocs/op&lt;/th&gt;
&lt;th&gt;Gap on the same seed-47 matrix&lt;/th&gt;
&lt;th&gt;Published claim&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Held-Karp&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;313.6 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;172.1 KiB&lt;/td&gt;
&lt;td&gt;68&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;exact + proven optimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch-and-Bound&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;388.9 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;14.39 KiB&lt;/td&gt;
&lt;td&gt;197&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;exact + proven optimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Blossom&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;25.24 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;9.887 KiB&lt;/td&gt;
&lt;td&gt;158&lt;/td&gt;
&lt;td&gt;1.409%&lt;/td&gt;
&lt;td&gt;formal 1.5 approximation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Greedy&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;16.26 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.809 KiB&lt;/td&gt;
&lt;td&gt;96&lt;/td&gt;
&lt;td&gt;1.409%&lt;/td&gt;
&lt;td&gt;no formal ratio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2-opt&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7.008 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.562 KiB&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;heuristic; no proof of optimality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3-opt&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;37.60 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3.844 KiB&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;heuristic; no proof of optimality&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The CSV for that exact fixture records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Branch-and-Bound      cost=26037.596462281  nodes=3663  exact=true  optimal=true
2-opt                 cost=26037.596462281  iters=9     exact=false optimal=false
3-opt                 cost=26037.596462281  iters=0     exact=false optimal=false
Christofides/Blossom  cost=26404.536340990  ratio=1.5
Christofides/Greedy   cost=26404.536340990  ratio=0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The costs are identical, while the metadata differs because only the exact runs completed a proof of global optimality.&lt;/p&gt;

&lt;p&gt;The equal-&lt;code&gt;n&lt;/code&gt; table is a performance comparison for one fixed workload, not a universal solver ranking. That caveat matters: the permanent package benchmarks deliberately exercise very different regimes (&lt;code&gt;n=12&lt;/code&gt; Held-Karp, &lt;code&gt;n=14&lt;/code&gt; Branch-and-Bound, &lt;code&gt;n=200&lt;/code&gt; Christofides, &lt;code&gt;n=500&lt;/code&gt; 2-opt), so putting those permanent numbers into one "fastest TSP algorithm" chart would be nonsense.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the 1.5 guarantee cost here?
&lt;/h2&gt;

&lt;p&gt;The cleanest apples-to-apples regression pair in the package changes only the matching policy inside Christofides. Both use the same deterministic metric &lt;code&gt;n=200&lt;/code&gt; fixture. Local search is disabled.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Matching policy&lt;/th&gt;
&lt;th&gt;sec/op&lt;/th&gt;
&lt;th&gt;B/op&lt;/th&gt;
&lt;th&gt;allocs/op&lt;/th&gt;
&lt;th&gt;Formal ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blossom exact MWPM&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;70.13 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.714 MiB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8,925&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1.5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Greedy matching&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.655 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;450.4 KiB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1,401&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foluzcjjbhc14pqv0bp44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foluzcjjbhc14pqv0bp44.png" alt=" " width="799" height="412"&gt;&lt;/a&gt;&lt;/p&gt;
Same n=200 fixture and outer Christofides pipeline; only the matching policy changes.



&lt;p&gt;On this machine and fixture, the exact-matching pipeline is about &lt;strong&gt;26.4× slower&lt;/strong&gt;, uses &lt;strong&gt;6.2×&lt;/strong&gt; the bytes per operation, and performs &lt;strong&gt;6.4×&lt;/strong&gt; the allocations.&lt;/p&gt;

&lt;p&gt;This comparison is narrow enough to be useful: the outer algorithm, matrix family, size, and local-search setting stay fixed. The changed subroutine is also the one that carries the proof obligation.&lt;/p&gt;

&lt;p&gt;The isolated dense Blossom benchmark makes the growth visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;32 odd vertices   2.350 ms
64               12.36  ms
128              57.72  ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From 32 to 128 odd vertices, measured solve time increased about &lt;strong&gt;24.6×&lt;/strong&gt; on this workload.&lt;/p&gt;

&lt;p&gt;That does not make Greedy "better" or Blossom "slow". It tells me what the stronger matching policy costs in this implementation, on this machine, for these fixtures.&lt;/p&gt;

&lt;h2&gt;
  
  
  A claim-first way to choose the solver
&lt;/h2&gt;

&lt;p&gt;A size-only rule is too vague for exact TSP. &lt;code&gt;v0.1.0&lt;/code&gt; ships Held-Karp with a &lt;strong&gt;soft &lt;code&gt;MaxExactN&lt;/code&gt; guard whose default is 16&lt;/strong&gt;. Callers may raise that option, but the underlying cost remains &lt;code&gt;O(n²·2ⁿ)&lt;/code&gt; time and &lt;code&gt;O(n·2ⁿ)&lt;/code&gt; memory. Branch-and-Bound has no comparable fixed vertex cap; its worst case is exponential and its practical limit depends on the matrix, lower bound, incumbent quality, and wall-clock budget.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Start here&lt;/th&gt;
&lt;th&gt;Do not say&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Predictable exact DP and &lt;code&gt;n&lt;/code&gt; fits the configured &lt;code&gt;MaxExactN&lt;/code&gt; plus memory/time budget (default guard: 16)&lt;/td&gt;
&lt;td&gt;Held-Karp&lt;/td&gt;
&lt;td&gt;Raising &lt;code&gt;MaxExactN&lt;/code&gt; makes the exponential state space cheap.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global optimum required but Held-Karp's DP budget is unattractive; pruning may help and runtime may be instance-dependent&lt;/td&gt;
&lt;td&gt;Branch-and-Bound + explicit &lt;code&gt;TimeLimit&lt;/code&gt;; use an admissible bound&lt;/td&gt;
&lt;td&gt;A timeout incumbent is optimal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Symmetric complete metric input; formal approximation bound required&lt;/td&gt;
&lt;td&gt;Christofides + Blossom&lt;/td&gt;
&lt;td&gt;Greedy matching keeps the 1.5 proof.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Locally optimal route required; global proof is unnecessary or computationally infeasible&lt;/td&gt;
&lt;td&gt;2-opt / 3-opt with explicit move limits&lt;/td&gt;
&lt;td&gt;Local optimum is global optimum.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Directed/asymmetric cost&lt;/td&gt;
&lt;td&gt;Held-Karp / Branch-and-Bound when exact search is feasible, otherwise directed local search&lt;/td&gt;
&lt;td&gt;Symmetrization is harmless cleanup.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing edges encoded as &lt;code&gt;+Inf&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Metric closure only when that transformation is valid for the domain&lt;/td&gt;
&lt;td&gt;Derived closure distances are original edges.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metric assumptions are unknown&lt;/td&gt;
&lt;td&gt;Validate them or publish no ratio&lt;/td&gt;
&lt;td&gt;Symmetry alone proves triangle inequality.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;
  Reproduction details
  &lt;p&gt;The benchmark output recorded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository's permanent regression benchmarks live in &lt;code&gt;tsp/bench_test.go&lt;/code&gt;. The equal-&lt;code&gt;n&lt;/code&gt; benchmark and the CSV quality harness were article-only local files; I ran them, kept the raw results, and did not add them to the library.&lt;/p&gt;

&lt;p&gt;Exact regression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 go &lt;span class="nb"&gt;test&lt;/span&gt; ./tsp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-run&lt;/span&gt; &lt;span class="s1"&gt;'^$'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="s1"&gt;'Benchmark(HeldKarp|BranchBound)'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-cpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10 &lt;span class="nt"&gt;-benchtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Practical regimes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 go &lt;span class="nb"&gt;test&lt;/span&gt; ./tsp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-run&lt;/span&gt; &lt;span class="s1"&gt;'^$'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="s1"&gt;'Benchmark(Christofides|TwoOpt|ThreeOpt)'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-cpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10 &lt;span class="nt"&gt;-benchtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Blossom regression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 go &lt;span class="nb"&gt;test&lt;/span&gt; ./tsp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-run&lt;/span&gt; &lt;span class="s1"&gt;'^$'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="s1"&gt;'BenchmarkBlossom'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-cpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10 &lt;span class="nt"&gt;-benchtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For strict reproduction, publish the exact commit SHA alongside the raw benchmark files. The Go version was not present in the benchmark outputs I kept, so I would not invent it after the fact.&lt;/p&gt;



&lt;br&gt;
&lt;p&gt;&lt;/p&gt;

&lt;p&gt;There was no single winner in these fixtures. Local search often matched the exact optimum cost; Christofides carried the stronger worst-case statement; exact methods were the only ones allowed to set &lt;code&gt;Optimal=true&lt;/code&gt;. The benchmark and the theorem ranked the same solvers differently.&lt;/p&gt;

&lt;p&gt;If a caller cannot distinguish &lt;strong&gt;proven&lt;/strong&gt;, &lt;strong&gt;bounded&lt;/strong&gt;, &lt;strong&gt;timed out&lt;/strong&gt;, and merely &lt;strong&gt;good on this run&lt;/strong&gt;, the solver is hiding state it already knows.&lt;/p&gt;

&lt;p&gt;Code and contracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lvlath/go/tree/v0.1.0/tsp" rel="noopener noreferrer"&gt;TSP package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lvlath/go/blob/v0.1.0/tsp/example_test.go" rel="noopener noreferrer"&gt;Runnable scenarios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pkg.go.dev/github.com/lvlath/go@v0.1.0/tsp" rel="noopener noreferrer"&gt;Go Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lvlath/go/blob/v0.1.0/docs/TSP.md" rel="noopener noreferrer"&gt;Long-form TSP documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>algorithms</category>
      <category>opensource</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>The Algorithm Was Correct. The Graph Contract Was Not.</title>
      <dc:creator>Kyrylo Malovychko</dc:creator>
      <pubDate>Wed, 05 Aug 2026 15:01:45 +0000</pubDate>
      <link>https://dev.to/katalvlaran/the-algorithm-was-correct-the-graph-contract-was-not-de8</link>
      <guid>https://dev.to/katalvlaran/the-algorithm-was-correct-the-graph-contract-was-not-de8</guid>
      <description>&lt;p&gt;&lt;strong&gt;I tried to build an algorithm-heavy service with AI before I understood the algorithms well enough to specify them. A few days later I had a lot of code, no coherent graph, and one decision that changed the next two years of my work.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I began with a shortcut.&lt;/p&gt;

&lt;p&gt;The service I wanted to build depended on a long list of algorithms. Some were familiar. Some I remembered from university only as names, formulas, and half-erased diagrams. A few I did not understand well enough to control at all.&lt;/p&gt;

&lt;p&gt;AI looked like the obvious accelerator. I could describe the pieces, ask for implementations, join them later, and learn the difficult parts while the product was already taking shape.&lt;/p&gt;

&lt;p&gt;Several days of hard work produced files at an impressive rate.&lt;/p&gt;

&lt;p&gt;There were interfaces. Options. Callbacks. Result types. Comments that sounded confident.&lt;/p&gt;

&lt;p&gt;Almost none of it belonged to the same system.&lt;/p&gt;

&lt;p&gt;I could not even make BFS and DFS work against one graph model that I understood. One implementation expected adjacency in one shape, the other quietly assumed another. Options changed behaviour I had never defined. Results returned values, but not guarantees. I could not explain what had happened, why the answer was correct, or which part of it would remain stable after the next refactor.&lt;/p&gt;

&lt;p&gt;I was not mildly dissatisfied. I was completely disappointed.&lt;/p&gt;

&lt;p&gt;There was exactly one useful result: I stopped trusting AI with the parts I had not learned. If these algorithms were going to sit under a real service, I had to understand them and build them myself.&lt;/p&gt;

&lt;p&gt;That was the point of no return.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code was not the missing part
&lt;/h2&gt;

&lt;p&gt;It would be easy to turn this into another story about AI producing bad code. That is not the lesson.&lt;/p&gt;

&lt;p&gt;The deeper mistake was mine. I had asked for implementations before I could state the contract around them.&lt;/p&gt;

&lt;p&gt;What graph shapes were legal? Was neighbour order observable? Who owned tie-breaking? Could edges be directed, undirected, or mixed? What did &lt;code&gt;0&lt;/code&gt; mean inside a matrix? How was an unreachable target represented? Did a result carry a path, a predecessor map, a cut, a tree, or only a number? Could a caller classify failures without parsing an error string?&lt;/p&gt;

&lt;p&gt;I had no precise answers. AI filled the gaps with plausible assumptions.&lt;/p&gt;

&lt;p&gt;That is what makes this class of failure dangerous. Broken syntax is cheap to reject. Plausible code is not. It compiles, returns something, and invites the rest of the system to depend on decisions nobody made consciously.&lt;/p&gt;

&lt;p&gt;A function can be mathematically correct and still publish an unusable software contract.&lt;/p&gt;

&lt;p&gt;The first example was neighbour order.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code insert 1: the graph that looks harmless
&lt;/h3&gt;

&lt;p&gt;This is a reduced reconstruction of the pattern, not the original generated code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;naive&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Graph&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;Graph&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;AddUndirected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}{}&lt;/span&gt;
    &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;Graph&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Neighbors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;neighbor&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;neighbor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This graph is small, normal Go. It stores undirected connections and exposes neighbours.&lt;/p&gt;

&lt;p&gt;It also returns a slice without defining its order.&lt;/p&gt;

&lt;p&gt;Go map iteration order is not a public ordering policy. The same topology can reach a traversal through a different neighbour sequence. The graph has already influenced the result before BFS or DFS runs, but no package owns the decision and no caller knows whether the order can be relied on.&lt;/p&gt;

&lt;p&gt;Maybe order does not matter to the mathematics. It still matters to software.&lt;/p&gt;

&lt;p&gt;The slice may be logged, serialised, compared in a golden test, used for equal-cost tie-breaking, or shown to a user. Once callers can observe it, “we never intended the order to matter” is not much of a defence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code insert 2: a correct BFS inherits the uncertainty
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;naive&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BFS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;Graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Neighbors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
            &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose &lt;code&gt;api&lt;/code&gt; connects to both &lt;code&gt;auth&lt;/code&gt; and &lt;code&gt;cache&lt;/code&gt;, and both are one hop away.&lt;/p&gt;

&lt;p&gt;These outputs can both satisfy the BFS distance property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[api auth cache db worker]
[api cache auth db worker]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The algorithm is not necessarily wrong.&lt;/p&gt;

&lt;p&gt;The product can still be wrong.&lt;/p&gt;

&lt;p&gt;If the sequence drives a deployment plan, chooses the first equal candidate, appears in a reproducible report, or becomes part of a test fixture, two mathematically legal answers are not an adequate API contract.&lt;/p&gt;

&lt;p&gt;That was the first thing I had failed to specify. I had named the algorithm. I had not defined the observable law around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to the mathematics, one stubborn step at a time
&lt;/h2&gt;

&lt;p&gt;I stopped generating more code and went back to theory.&lt;/p&gt;

&lt;p&gt;That phase was slower than I expected. Article after article, I found dense formulas with almost no reasoning, implementations without a mathematical explanation, questionable translations, and examples that demonstrated syntax but taught very little about behaviour.&lt;/p&gt;

&lt;p&gt;I had been naïve enough to think I would quickly recover the university mathematics and continue with the product.&lt;/p&gt;

&lt;p&gt;Instead, I moved one stubborn step at a time.&lt;/p&gt;

&lt;p&gt;Graphs and matrices came back first. BFS and DFS followed. Dijkstra and minimum spanning trees were where irritation turned into a decision.&lt;/p&gt;

&lt;p&gt;The foundations were not new. Much of the mathematics predates the modern software industry. Yet the useful knowledge was split across papers, tutorials, source repositories, paid material, shallow snippets, and documentation that stopped exactly where the uncomfortable production questions began.&lt;/p&gt;

&lt;p&gt;I kept asking the same thing:&lt;/p&gt;

&lt;p&gt;Why is there no free, coherent source where the mathematics is explained, the implementation is open, the contracts are explicit, and the examples are worth running?&lt;/p&gt;

&lt;p&gt;Eventually the answer became obvious.&lt;/p&gt;

&lt;p&gt;Build it.&lt;/p&gt;

&lt;p&gt;Not another catalogue of textbook functions. The source I had been looking for: something a developer could study, use, challenge, and improve without surrendering the difficult parts to a black box.&lt;/p&gt;

&lt;h2&gt;
  
  
  A graph is not “vertices plus edges”
&lt;/h2&gt;

&lt;p&gt;My early model of a graph was too weak. I treated it as a container.&lt;/p&gt;

&lt;p&gt;A graph is also a domain of legal states.&lt;/p&gt;

&lt;p&gt;Are edges directed? Are non-zero weights allowed? Can directed and undirected edges coexist? Are loops valid? Are parallel edges distinct facts or duplicate input? Does adding an edge create missing vertices? Can an option rewrite endpoints after validation? What survives a clone? Which values alias live storage?&lt;/p&gt;

&lt;p&gt;If these answers live only in comments, invalid topology travels until a later algorithm discovers it in the worst possible place.&lt;/p&gt;

&lt;p&gt;Dijkstra should not be the first layer to reveal that the graph never validated weights. An MST implementation should not guess whether parallel edges are legal. DFS should not discover halfway through cycle analysis that “directed” meant “usually directed.”&lt;/p&gt;

&lt;p&gt;The capabilities belong at construction and mutation boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code insert 3: make the graph policy executable
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/lvlath/go/core"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithDirected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithWeighted&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"db"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"edge-api-db"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"edge-api-cache"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"edge-api-auth"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NeighborIDs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// [auth cache db]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The policy is visible.&lt;/p&gt;

&lt;p&gt;The graph is undirected by default. Non-zero weights are legal. Edge identities are explicit. &lt;code&gt;NeighborIDs&lt;/code&gt; publishes unique adjacent vertex IDs in lexicographic order.&lt;/p&gt;

&lt;p&gt;The insertion order is not the contract.&lt;/p&gt;

&lt;p&gt;A caller can dislike the policy, measure the cost, or propose another one. Fine. At least the disagreement is now concrete and testable.&lt;/p&gt;

&lt;p&gt;That is the point of a contract. It does not eliminate trade-offs. It stops them hiding inside incidental implementation behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  The number is not the meaning
&lt;/h2&gt;

&lt;p&gt;Ordering was only the first hidden contract.&lt;/p&gt;

&lt;p&gt;Numeric meaning was worse because the wrong answer could still look perfectly reasonable.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;0&lt;/code&gt; can be a real zero-cost edge. In a classic adjacency matrix, the same &lt;code&gt;0&lt;/code&gt; can mean no edge at all. &lt;code&gt;+Inf&lt;/code&gt; can mean no direct edge, no known path, or an uninitialised cell. A negative weight is legal for one algorithm and forbidden for another. &lt;code&gt;NaN&lt;/code&gt; can poison a matrix while every surrounding type remains valid.&lt;/p&gt;

&lt;p&gt;No number carries its domain semantics with it.&lt;/p&gt;

&lt;p&gt;The representation has to declare the policy.&lt;/p&gt;

&lt;p&gt;This became a hard boundary in &lt;code&gt;lvlath/matrix&lt;/code&gt;. Zero-preserving weighted adjacency uses finite &lt;code&gt;0&lt;/code&gt; for a real edge and &lt;code&gt;+Inf&lt;/code&gt; for absence. Metric closure uses &lt;code&gt;0&lt;/code&gt; on the diagonal and &lt;code&gt;+Inf&lt;/code&gt; for unreachable pairs. Then it refuses to export those derived distances as if they were original graph edges.&lt;/p&gt;

&lt;p&gt;That refusal is not inconvenience. It prevents a false topology.&lt;/p&gt;

&lt;p&gt;The matrix problem deserves its own article, but the lesson belongs here: a perfect algorithm cannot recover information that the representation erased before the algorithm started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errors should survive better wording
&lt;/h2&gt;

&lt;p&gt;The prototypes returned &lt;code&gt;error&lt;/code&gt; values. That did not make the failures useful.&lt;/p&gt;

&lt;p&gt;If a caller has to compare text, improved diagnostics become breaking changes. More importantly, different operational states collapse into one vague failure path.&lt;/p&gt;

&lt;p&gt;Unknown is not unreachable. Unreachable is not “path tracking was disabled.” Cancellation is not resource exhaustion. Invalid topology is not an empty result.&lt;/p&gt;

&lt;p&gt;Named error identity is not exciting. It is dependable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code insert 4: classify the failure, do not parse the sentence
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"errors"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/lvlath/go/core"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewGraph&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// unweighted by default&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrBadWeight&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c"&gt;// true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ErrBadWeight&lt;/code&gt; is useful because code can react to its identity while the surrounding diagnostics improve.&lt;/p&gt;

&lt;p&gt;The same discipline continues above the graph layer. A shortest-path package should distinguish an unknown target from a known unreachable one. A cycle detector should return a witness. A max-flow result should expose the residual network when the caller needs to inspect the bottleneck. A DTW result should distinguish alignment cost from the recovered path.&lt;/p&gt;

&lt;p&gt;A number without evidence is often just a polite version of “trust me.”&lt;/p&gt;

&lt;p&gt;I had already tried that approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  v0.0.1: publish the weakness, not the mythology
&lt;/h2&gt;

&lt;p&gt;The first architecture looked sensible when it lived only in my head:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph/
├── algorithms/
├── core/
└── matrix/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;BFS, DFS, Dijkstra, Prim, and Kruskal shared one algorithm directory. &lt;code&gt;core&lt;/code&gt; held the graph. &lt;code&gt;matrix&lt;/code&gt; handled adjacency and incidence representations.&lt;/p&gt;

&lt;p&gt;Simple.&lt;/p&gt;

&lt;p&gt;Too simple.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftpzrsoh8w0ru3ikfwtld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftpzrsoh8w0ru3ikfwtld.png" alt=" " width="576" height="1712"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1. The v0.0.1 structure. Useful as a public baseline; not a structure worth preserving.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Each algorithm wanted its own options, result type, errors, examples, ownership rules, complexity statement, and failure surface. Keeping them together encouraged convenient shared assumptions and made every explanation blur into the next one.&lt;/p&gt;

&lt;p&gt;My second mistake was more expensive because I made it deliberately: implement first, document later.&lt;/p&gt;

&lt;p&gt;I told myself that serious documentation should wait until the code worked. In practice, the delay allowed unclear behaviour to spread. When I finally tried to describe every public option, error, result, complexity claim, ownership rule, and edge case in one consistent format, the contradictions became impossible to ignore.&lt;/p&gt;

&lt;p&gt;Another restructuring followed.&lt;/p&gt;

&lt;p&gt;Documentation written after an API hardens is often archaeology. I had created my own dig site.&lt;/p&gt;

&lt;p&gt;I shelved a chess engine. I abandoned the deeper-analysis service that had started the whole journey. The list of planned algorithms changed too. Early ambitions included SAX, HMM, ARIMA, GBM, and GJR-GARCH. Shipping that breadth on a weak foundation would have repeated the original mistake at a larger scale.&lt;/p&gt;

&lt;p&gt;So I narrowed the path.&lt;/p&gt;

&lt;p&gt;Graph and matrix first. Then BFS, DFS, Dijkstra, MST, flow, TSP, and DTW in an order a reader could actually follow.&lt;/p&gt;

&lt;p&gt;I released &lt;code&gt;v0.0.1&lt;/code&gt; anyway.&lt;/p&gt;

&lt;p&gt;It was primitive. Some parts were awkward. That was the point. I needed a real tag, a version I could install outside the IDE, and a public baseline that made weak seams visible.&lt;/p&gt;

&lt;p&gt;Then the first email arrived.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first user changed the quality bar
&lt;/h2&gt;

&lt;p&gt;Another Go developer had found lvlath while looking for a graph library.&lt;/p&gt;

&lt;p&gt;He was building a package for scheduling binary execution. Users could define arguments, conflicts, and dependencies between those arguments. He wanted to know whether graph theory, and lvlath specifically, could help him check those relationships efficiently even at a small scale.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmby93osw6rundwa0alve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmby93osw6rundwa0alve.png" alt=" " width="800" height="691"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2. The first external question was not about an academic demo. It was about conflicts, dependencies, and a real package design.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That message did not prove the library was good.&lt;/p&gt;

&lt;p&gt;It proved the problem was not mine alone.&lt;/p&gt;

&lt;p&gt;Until then, I could still treat the quality bar as personal. After that email, every ambiguous contract became someone else's risk. Another developer was ready to build on assumptions I had made.&lt;/p&gt;

&lt;p&gt;“Works” stopped being enough.&lt;/p&gt;

&lt;p&gt;So did 80 percent. Then 90. Then 95.&lt;/p&gt;

&lt;p&gt;Not because a percentage can certify a library. It cannot. The numbers describe the movement of the bar: from a personal prototype toward public responsibility. Tests had to cover validation, medium cases, adversarial boundaries, deterministic repetition, race safety, and result witnesses. Documentation had to match the implementation. Examples had to compile against the public API and teach a problem worth recognising.&lt;/p&gt;

&lt;p&gt;Praise would have felt good.&lt;/p&gt;

&lt;p&gt;A concrete question was better. It forced the project to answer somebody else's reality.&lt;/p&gt;

&lt;h2&gt;
  
  
  v0.1.0: separate the contracts
&lt;/h2&gt;

&lt;p&gt;The rebuilt structure is wider and much less accidental.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foie6qmfvigj5llxarvkj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foie6qmfvigj5llxarvkj.png" alt=" " width="496" height="1570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3. By v0.1.0, each algorithm owns a package boundary, while &lt;code&gt;docs/&lt;/code&gt; and &lt;code&gt;examples/&lt;/code&gt; are visible parts of the system.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One algorithm, one package.&lt;/p&gt;

&lt;p&gt;Not because directories are architecture by themselves, but because boundaries force questions into the open. BFS and DFS no longer need to pretend they share one result contract. Dijkstra can own target semantics. MST can separate strict-tree and forest behaviour. Flow can expose residual-network evidence. TSP can state solver method, assumptions, and stopping policy. DTW can distinguish cost from path recovery and memory mode.&lt;/p&gt;

&lt;p&gt;The documentation layer changed too.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;example_test.go&lt;/code&gt; scenarios are not decorative snippets. They are executable teaching material. The long-form &lt;code&gt;docs/*.md&lt;/code&gt; files explain the mathematics, the public contract, the failure modes, the complexity, and the operational traps. GoDoc states the API. Tests defend it. Source should not invent a fourth interpretation.&lt;/p&gt;

&lt;p&gt;This combination is the part I am most proud of.&lt;/p&gt;

&lt;p&gt;Not one clever function.&lt;/p&gt;

&lt;p&gt;The agreement between code, explanation, example, and test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests should defend promises, not accidents
&lt;/h2&gt;

&lt;p&gt;A happy-path test can preserve the wrong behaviour forever.&lt;/p&gt;

&lt;p&gt;If a test expects one traversal order but the API never promises an order, the test has converted an accident into a hidden requirement. If it reaches into private maps, it protects storage rather than caller behaviour. If it checks only a scalar cost, it can miss a broken witness.&lt;/p&gt;

&lt;p&gt;For neighbour ordering, the useful test is not “this insertion sequence produced this slice once.”&lt;/p&gt;

&lt;p&gt;It is “all supported construction histories publish the same documented surface.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Code insert 5: build the same graph three ways
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;core_test&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"slices"&lt;/span&gt;
    &lt;span class="s"&gt;"testing"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/lvlath/go/core"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestNeighborIDsIgnoreInsertionOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"db"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"db"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"db"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;want&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"db"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithDirected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NeighborIDs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;slices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"insertion %v: got %v, want %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test does not care whether adjacency is stored in maps, sorted slices, trees, or a compact representation not yet implemented. It defends only the behaviour the caller is entitled to observe.&lt;/p&gt;

&lt;p&gt;That kind of test survives a real refactor.&lt;/p&gt;

&lt;p&gt;The same idea scales. Validate a path independently from the solver. Verify that an MST is acyclic and spans the required component. Check flow conservation and residual capacity instead of trusting one maximum. Permute insertion order. Fuzz invalid option combinations. Separate race safety from snapshot guarantees.&lt;/p&gt;

&lt;p&gt;A green suite is not proof by itself.&lt;/p&gt;

&lt;p&gt;But every public guarantee needs evidence strong enough to fail when the guarantee is broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  The current public promise
&lt;/h2&gt;

&lt;p&gt;The present module is not just a repository tree. It publishes a contract where people already look for Go packages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1rag4ut28mu7aife9x69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1rag4ut28mu7aife9x69.png" alt=" " width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4. The current public promise: the same input and policy should produce the same observable result surface, witness semantics, and failure class.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The sentence at the top of the documentation is deliberately strict:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Same graph, same options, same algorithm - same result surface, same witness semantics, same failure class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That promise is harder to maintain than implementing BFS.&lt;/p&gt;

&lt;p&gt;It has to survive new packages, performance work, refactors, better diagnostics, more examples, and eventually new major versions. It requires boring details: stable identities, explicit capabilities, sentinel errors, documented ownership, numerical semantics, cancellation behaviour, partial results, and tests that do not depend on private storage.&lt;/p&gt;

&lt;p&gt;Those details are the library.&lt;/p&gt;

&lt;p&gt;The algorithm is only the centre.&lt;/p&gt;

&lt;h2&gt;
  
  
  What remains unfinished
&lt;/h2&gt;

&lt;p&gt;There is plenty left to argue about.&lt;/p&gt;

&lt;p&gt;Matching implementations such as blossom and greedy matching currently sit inside &lt;code&gt;tsp&lt;/code&gt;; they may deserve clearer package boundaries. The planned catalogue is much larger than the current release. Future major versions will have to decide how far the ecosystem should expand without repeating the old mistake of breadth before a stable foundation.&lt;/p&gt;

&lt;p&gt;The project uses one Go module with multiple packages. That is deliberate today. It gives users one versioned dependency surface while each algorithm owns its public API. Splitting packages into separate modules would add release and compatibility cost; it should happen only when user evidence justifies it, not because more module files look more modular.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;v0.1.0&lt;/code&gt; is not a monument.&lt;/p&gt;

&lt;p&gt;Good.&lt;/p&gt;

&lt;p&gt;There is still time to challenge the contracts before they harden.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule I use now
&lt;/h2&gt;

&lt;p&gt;Before I blame an algorithm, I inspect the layer beneath it.&lt;/p&gt;

&lt;p&gt;Does the graph publish a stable vertex, edge, and neighbour order?&lt;/p&gt;

&lt;p&gt;Are directedness, weights, loops, parallel edges, and mixed edges validated as capabilities rather than suggested by comments?&lt;/p&gt;

&lt;p&gt;Do &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;+Inf&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;, negative values, and absence have one documented meaning in the current representation?&lt;/p&gt;

&lt;p&gt;Are identity, cloning, views, aliases, metadata, and ownership clear?&lt;/p&gt;

&lt;p&gt;Can software classify failures without parsing prose?&lt;/p&gt;

&lt;p&gt;Does the result carry enough evidence to inspect the answer: path, predecessor map, cycle witness, tree, cut, residual graph, tour, or alignment?&lt;/p&gt;

&lt;p&gt;Do the examples, tests, GoDoc, and long-form documentation describe the same behaviour?&lt;/p&gt;

&lt;p&gt;If the answer is “it depends,” that is not always a bug.&lt;/p&gt;

&lt;p&gt;It is a policy waiting for an owner.&lt;/p&gt;

&lt;h2&gt;
  
  
  The point of no return, revisited
&lt;/h2&gt;

&lt;p&gt;The original service never became the product I had imagined.&lt;/p&gt;

&lt;p&gt;The chess engine was shelved. The deeper-analysis project was abandoned. The first architecture was replaced. Documentation forced another round of redesign. The list of future algorithms kept growing while the release scope had to become narrower.&lt;/p&gt;

&lt;p&gt;That cost was real.&lt;/p&gt;

&lt;p&gt;It also produced something I had not planned: a public source for the next engineer who reaches the same wall.&lt;/p&gt;

&lt;p&gt;AI still has a place in my workflow. It can accelerate scaffolding, propose adversarial cases, compare designs, and reduce repetitive work. It cannot take responsibility for a mathematical contract I have not written.&lt;/p&gt;

&lt;p&gt;That responsibility remains mine.&lt;/p&gt;

&lt;p&gt;The first external user changed lvlath from a private attempt into a public obligation. The current structure, examples, documentation, and tests are how I am trying to honour it.&lt;/p&gt;

&lt;p&gt;If a guarantee is weak, open an issue. If an example is confusing, say exactly where. If an algorithm is missing, describe the real problem before naming the package. If the mathematics is wrong, bring a counterexample.&lt;/p&gt;

&lt;p&gt;I paid for the confusion once.&lt;/p&gt;

&lt;p&gt;The next engineer should not have to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before debugging the algorithm, ask whether the graph underneath it ever made a promise.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Which hidden contract has cost you the most: ordering, topology, numerical meaning, identity, mutation, or missing evidence?&lt;/p&gt;




&lt;h2&gt;
  
  
  Repository and references
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lvlath/go" rel="noopener noreferrer"&gt;lvlath/go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lvlath/go/tree/main/core" rel="noopener noreferrer"&gt;lvlath/core source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pkg.go.dev/github.com/lvlath/go/core" rel="noopener noreferrer"&gt;lvlath/core Go Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lvlath/go/issues/new/choose" rel="noopener noreferrer"&gt;Issue templates for defects, contract questions, and API proposals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.dev/ref/spec" rel="noopener noreferrer"&gt;Go language specification: map iteration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>algorithms</category>
      <category>architecture</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
