<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://algorist.com/algowiki_v2/index.php?action=history&amp;feed=atom&amp;title=TADM2E_1.26</id>
		<title>TADM2E 1.26 - Revision history</title>
		<link rel="self" type="application/atom+xml" href="https://algorist.com/algowiki_v2/index.php?action=history&amp;feed=atom&amp;title=TADM2E_1.26"/>
		<link rel="alternate" type="text/html" href="https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;action=history"/>
		<updated>2026-04-30T23:51:32Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.28.0</generator>

	<entry>
		<id>https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=1173&amp;oldid=prev</id>
		<title>Matt: Undo revision 1141 by FuckyouMatt (talk)</title>
		<link rel="alternate" type="text/html" href="https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=1173&amp;oldid=prev"/>
				<updated>2020-08-02T12:12:50Z</updated>
		
		<summary type="html">&lt;p&gt;Undo revision 1141 by &lt;a href=&quot;/algowiki_v2/index.php/Special:Contributions/FuckyouMatt&quot; title=&quot;Special:Contributions/FuckyouMatt&quot;&gt;FuckyouMatt&lt;/a&gt; (&lt;a href=&quot;/algowiki_v2/index.php?title=User_talk:FuckyouMatt&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User talk:FuckyouMatt (page does not exist)&quot;&gt;talk&lt;/a&gt;)&lt;/p&gt;
&lt;a href=&quot;https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;amp;diff=1173&amp;amp;oldid=1141&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Matt</name></author>	</entry>

	<entry>
		<id>https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=1141&amp;oldid=prev</id>
		<title>FuckyouMatt: Blanked the page</title>
		<link rel="alternate" type="text/html" href="https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=1141&amp;oldid=prev"/>
				<updated>2020-08-02T02:10:35Z</updated>
		
		<summary type="html">&lt;p&gt;Blanked the page&lt;/p&gt;
&lt;a href=&quot;https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;amp;diff=1141&amp;amp;oldid=942&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>FuckyouMatt</name></author>	</entry>

	<entry>
		<id>https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=942&amp;oldid=prev</id>
		<title>Matt: Undo revision 851 by Mgits (talk)</title>
		<link rel="alternate" type="text/html" href="https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=942&amp;oldid=prev"/>
				<updated>2020-07-23T15:53:14Z</updated>
		
		<summary type="html">&lt;p&gt;Undo revision 851 by &lt;a href=&quot;/algowiki_v2/index.php/Special:Contributions/Mgits&quot; title=&quot;Special:Contributions/Mgits&quot;&gt;Mgits&lt;/a&gt; (&lt;a href=&quot;/algowiki_v2/index.php?title=User_talk:Mgits&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User talk:Mgits (page does not exist)&quot;&gt;talk&lt;/a&gt;)&lt;/p&gt;
&lt;a href=&quot;https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;amp;diff=942&amp;amp;oldid=851&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Matt</name></author>	</entry>

	<entry>
		<id>https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=851&amp;oldid=prev</id>
		<title>Mgits: Blanked the page</title>
		<link rel="alternate" type="text/html" href="https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=851&amp;oldid=prev"/>
				<updated>2020-07-20T00:20:50Z</updated>
		
		<summary type="html">&lt;p&gt;Blanked the page&lt;/p&gt;
&lt;a href=&quot;https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;amp;diff=851&amp;amp;oldid=324&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Mgits</name></author>	</entry>

	<entry>
		<id>https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=324&amp;oldid=prev</id>
		<title>Mvolodin: Created page with &quot;Tests show that closest pairs heuristic generally performs better than nearest neighbour heuristic.&lt;br/&gt; Here's python implementation for &lt;b&gt;nearest neighbour&lt;/b&gt; heuristic: &lt;...&quot;</title>
		<link rel="alternate" type="text/html" href="https://algorist.com/algowiki_v2/index.php?title=TADM2E_1.26&amp;diff=324&amp;oldid=prev"/>
				<updated>2015-04-26T12:37:38Z</updated>
		
		<summary type="html">&lt;p&gt;Created page with &amp;quot;Tests show that closest pairs heuristic generally performs better than nearest neighbour heuristic.&amp;lt;br/&amp;gt; Here&amp;#039;s python implementation for &amp;lt;b&amp;gt;nearest neighbour&amp;lt;/b&amp;gt; heuristic: &amp;lt;...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Tests show that closest pairs heuristic generally performs better than nearest neighbour heuristic.&amp;lt;br/&amp;gt;&lt;br /&gt;
Here's python implementation for &amp;lt;b&amp;gt;nearest neighbour&amp;lt;/b&amp;gt; heuristic:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import random&lt;br /&gt;
import matplotlib.pyplot as plot&lt;br /&gt;
import matplotlib.cm as cm&lt;br /&gt;
import numpy as np&lt;br /&gt;
import math&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def draw_arrow(axis, p1, p2, linecolor, style='solid', text=&amp;quot;&amp;quot;, radius=0):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;draw an arrow connecting point 1 to point 2&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    axis.annotate(text,&lt;br /&gt;
              xy=p2,&lt;br /&gt;
              xycoords='data',&lt;br /&gt;
              xytext=p1,&lt;br /&gt;
              arrowprops=dict(arrowstyle=&amp;quot;-&amp;quot;, linestyle=style, linewidth=0.8, color=linecolor,&lt;br /&gt;
                                                connectionstyle=&amp;quot;arc3,rad=&amp;quot; + str(radius)),)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nearest neighbour heuristic&lt;br /&gt;
def nearest_neighbour(datapoints):&lt;br /&gt;
    x, y = 0, 1&lt;br /&gt;
    #pick random starting point and add it to path&lt;br /&gt;
    i = random.randint(0, len(datapoints) - 1)&lt;br /&gt;
    path = [datapoints[i]]&lt;br /&gt;
    del datapoints[i]&lt;br /&gt;
    i = 0&lt;br /&gt;
    # while there are points find the closest one to datapoints[i], add it to path&lt;br /&gt;
    while(len(datapoints) != 0):&lt;br /&gt;
        minlen = 1e124&lt;br /&gt;
        minind = -1&lt;br /&gt;
        for k in range(len(datapoints)):&lt;br /&gt;
            dist = math.hypot(datapoints[k][x] - path[i][x], datapoints[k][y] - path[i][y])&lt;br /&gt;
            if minlen &amp;gt; dist:&lt;br /&gt;
                minlen = dist&lt;br /&gt;
                minind = k&lt;br /&gt;
        path.append(datapoints[minind])&lt;br /&gt;
        del datapoints[minind]&lt;br /&gt;
        i += 1&lt;br /&gt;
    return path&lt;br /&gt;
&lt;br /&gt;
# MAIN SCRIPT&lt;br /&gt;
random.seed()&lt;br /&gt;
figure = plot.figure()&lt;br /&gt;
axis = figure.add_subplot(111)&lt;br /&gt;
&lt;br /&gt;
n = 6&lt;br /&gt;
points = [(random.uniform(0.01, 0.99), random.uniform(0.01, 0.99)) for i in range(n)]&lt;br /&gt;
# points for line&lt;br /&gt;
points = [(0.3, 0.2), (0.25, 0.2), (0.5, 0.2), (0.7, 0.2), (0.6, 0.2), (0.8, 0.2)]&lt;br /&gt;
&lt;br /&gt;
# find shortest path&lt;br /&gt;
path_points = nearest_neighbour(points)&lt;br /&gt;
&lt;br /&gt;
# draw path&lt;br /&gt;
colors = cm.rainbow(np.linspace(0, 1, len(path_points)))&lt;br /&gt;
plot.scatter([i[0] for i in path_points], [i[1] for i in path_points], color=colors)&lt;br /&gt;
# draw shortest path from point[0] to point[n-1]:&lt;br /&gt;
draw_arrow(axis, path_points[0], path_points[1], colors[0], style='solid', radius=0.3)&lt;br /&gt;
for i in range(1, len(path_points)-1):&lt;br /&gt;
    draw_arrow(axis, path_points[i], path_points[i + 1], colors[i], radius=0.3)&lt;br /&gt;
draw_arrow(axis, path_points[n - 1], path_points[0], colors[n-1], style='dashed', radius=0.3)&lt;br /&gt;
&lt;br /&gt;
plot.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;Python implementation of &amp;lt;b&amp;gt;closest pair&amp;lt;/b&amp;gt; heuristic&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import random&lt;br /&gt;
import matplotlib.pyplot as plot&lt;br /&gt;
import matplotlib.cm as cm&lt;br /&gt;
import numpy as np&lt;br /&gt;
import math&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def draw_arrow(axis, p1, p2, linecolor, style='solid', text = &amp;quot;&amp;quot;, radius = 0):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;draw an arrow connecting point 1 to point 2&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    axis.annotate(text,&lt;br /&gt;
              xy=p2,&lt;br /&gt;
              xycoords='data',&lt;br /&gt;
              xytext=p1,&lt;br /&gt;
              arrowprops=dict(arrowstyle=&amp;quot;-&amp;quot;, linestyle=style, linewidth=0.8, color=linecolor,&lt;br /&gt;
                                                connectionstyle=&amp;quot;arc3,rad=&amp;quot; + str(radius)),)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#closest pair heuristic&lt;br /&gt;
def closest_pair(points):&lt;br /&gt;
    distance = lambda c1p, c2p:  math.hypot(c1p[0] - c2p[0], c1p[1] - c2p[1])&lt;br /&gt;
    chains = [[points[i]] for i in range(len(points))]&lt;br /&gt;
    edges = []&lt;br /&gt;
    for i in range(len(points)-1):&lt;br /&gt;
        dmin = float(&amp;quot;inf&amp;quot;)  # infinitely big distance&lt;br /&gt;
        # test each chain against each other chain&lt;br /&gt;
        for chain1 in chains:&lt;br /&gt;
            for chain2 in [item for item in chains if item is not chain1]:&lt;br /&gt;
                # test each chain1 endpoint against each of chain2 endpoints&lt;br /&gt;
                for c1ind in [0, len(chain1) - 1]:&lt;br /&gt;
                    for c2ind in [0, len(chain2) - 1]:&lt;br /&gt;
                        dist = distance(chain1[c1ind], chain2[c2ind])&lt;br /&gt;
                        if dist &amp;lt; dmin:&lt;br /&gt;
                            dmin = dist&lt;br /&gt;
                            # remember endpoints as closest pair&lt;br /&gt;
                            chain2link1, chain2link2 = chain1, chain2&lt;br /&gt;
                            point1, point2 = chain1[c1ind], chain2[c2ind]&lt;br /&gt;
        # connect two closest points&lt;br /&gt;
        edges.append((point1, point2))&lt;br /&gt;
&lt;br /&gt;
        chains.remove(chain2link1)&lt;br /&gt;
        chains.remove(chain2link2)&lt;br /&gt;
        if len(chain2link1) &amp;gt; 1:&lt;br /&gt;
            chain2link1.remove(point1)&lt;br /&gt;
        if len(chain2link2) &amp;gt; 1:&lt;br /&gt;
            chain2link2.remove(point2)&lt;br /&gt;
        linkedchain = chain2link1&lt;br /&gt;
        linkedchain.extend(chain2link2)&lt;br /&gt;
        chains.append(linkedchain)&lt;br /&gt;
    # connect first endpoint to last one&lt;br /&gt;
    edges.append((chains[0][0], chains[0][len(chains[0])-1]))&lt;br /&gt;
    return chains[0], edges&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# MAIN SCRIPT&lt;br /&gt;
random.seed()&lt;br /&gt;
figure = plot.figure()&lt;br /&gt;
axis = figure.add_subplot(111)&lt;br /&gt;
&lt;br /&gt;
n = 6&lt;br /&gt;
points = [(random.uniform(0.01, 0.99), random.uniform(0.01, 0.99)) for i in range(n)]&lt;br /&gt;
# six points for a rectangle&lt;br /&gt;
points = [(0.3, 0.2), (0.3, 0.4), (0.501, 0.4), (0.501, 0.2), (0.702, 0.4), (0.702, 0.2)]&lt;br /&gt;
&lt;br /&gt;
#find shortest path&lt;br /&gt;
path_points, edges = closest_pair(points)&lt;br /&gt;
&lt;br /&gt;
#draw path&lt;br /&gt;
colors = cm.rainbow(np.linspace(0, 1, len(path_points)))&lt;br /&gt;
plot.scatter([i[0] for i in points], [i[1] for i in points], color=colors)&lt;br /&gt;
# draw shortest path from point[0] to point[n-1]:&lt;br /&gt;
for i in range(len(edges)):&lt;br /&gt;
    draw_arrow(axis, edges[i][0], edges[i][1], 'black', radius=0.)&lt;br /&gt;
&lt;br /&gt;
plot.show()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;The &amp;lt;b&amp;gt;minimum angle with randomised centroid heuristic&amp;lt;/b&amp;gt; solves both cases closest pair and nearest neighbour can't handle.&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Calculate the centroid (geometric mean of x and y coordinates) of all points given. Add a little offset to centroid, that allows to solve cases when points form a line.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Find the point that is furthermost from centroid. Let's call it point1&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Find point2 that comprises the smallest angle point1-centroid-point2&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Connect point1 and point2 with an edge.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Repeat from step 3 with point2.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import random&lt;br /&gt;
import matplotlib.pyplot as plot&lt;br /&gt;
import matplotlib.cm as cm&lt;br /&gt;
import numpy as np&lt;br /&gt;
import math&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def draw_arrow(axis, p1, p2, linecolor, style='solid', text = &amp;quot;&amp;quot;, radius = 0):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;draw an arrow connecting point 1 to point 2&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    axis.annotate(text,&lt;br /&gt;
              xy=p2,&lt;br /&gt;
              xycoords='data',&lt;br /&gt;
              xytext=p1,&lt;br /&gt;
              arrowprops=dict(arrowstyle=&amp;quot;-&amp;quot;, linestyle=style, linewidth=0.8, color=linecolor,&lt;br /&gt;
                                                connectionstyle=&amp;quot;arc3,rad=&amp;quot; + str(radius)),)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def angle_degrees(p1, center, p2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;angle in radians&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    distance = lambda c1p, c2p:  math.hypot(c1p[0] - c2p[0], c1p[1] - c2p[1])&lt;br /&gt;
    a = distance(center, p1)&lt;br /&gt;
    b = distance(center, p2)&lt;br /&gt;
    c = distance(p2, p1)&lt;br /&gt;
    cosine = (a**2 + b**2 - c**2) / (2*a*b)&lt;br /&gt;
    return math.acos(min(max(cosine, -1), 1))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def centroid(points):&lt;br /&gt;
    center = (sum([point[0] for point in points])/len(points) + random.uniform(0.010, 0.015),&lt;br /&gt;
              sum([point[1] for point in points])/len(points) + random.uniform(0.010, 0.015))&lt;br /&gt;
    edges = []&lt;br /&gt;
    # remember how many connections a point has. start with 0 connections&lt;br /&gt;
    uses = dict([(point, 0) for point in points])&lt;br /&gt;
    # start with the furthermost point&lt;br /&gt;
    point1 = points[0]&lt;br /&gt;
    longest = math.hypot(center[0] - point1[0], center[1] - point1[1])&lt;br /&gt;
    for pt in points:&lt;br /&gt;
        dist = math.hypot(center[0] - pt[0], center[1] - pt[1])&lt;br /&gt;
        if dist &amp;gt; longest:&lt;br /&gt;
            longest = dist&lt;br /&gt;
            point1 = pt&lt;br /&gt;
    # for every point find the other one that comprises the SMALLEST angle poin1-center-point2&lt;br /&gt;
    while True:&lt;br /&gt;
        if uses[point1] &amp;lt; 2:&lt;br /&gt;
            min_angle = 1e34&lt;br /&gt;
            point_to_connect = None&lt;br /&gt;
            # point must not be used more than twice!&lt;br /&gt;
            for point2 in [item for item in points if item is not point1]:&lt;br /&gt;
                angle = angle_degrees(point1, center, point2)&lt;br /&gt;
                if not (point1, point2) in edges and not (point2, point1) in edges and uses[point2] &amp;lt; 1 and\&lt;br /&gt;
                        angle &amp;lt; min_angle:&lt;br /&gt;
                    min_angle = angle&lt;br /&gt;
                    point_to_connect = point2&lt;br /&gt;
            if point_to_connect is not None:&lt;br /&gt;
                edges.append((point1, point_to_connect))&lt;br /&gt;
                uses[point1] += 1&lt;br /&gt;
                uses[point_to_connect] += 1&lt;br /&gt;
                point1 = point_to_connect&lt;br /&gt;
            else:&lt;br /&gt;
                break&lt;br /&gt;
        else:&lt;br /&gt;
            break&lt;br /&gt;
    # connect the last two points&lt;br /&gt;
    last_points = [k for k, v in uses.iteritems() if v == 1]&lt;br /&gt;
    assert(len(last_points) == 2)&lt;br /&gt;
    edges.append((last_points[0], last_points[1]))&lt;br /&gt;
&lt;br /&gt;
    return edges, center&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# MAIN SCRIPT&lt;br /&gt;
random.seed()&lt;br /&gt;
figure = plot.figure()&lt;br /&gt;
axis = figure.add_subplot(111)&lt;br /&gt;
&lt;br /&gt;
n = random.randint(6, 10)&lt;br /&gt;
points = [(random.uniform(0.01, 0.99), random.uniform(0.01, 0.99)) for i in range(n)]&lt;br /&gt;
# points for line&lt;br /&gt;
#points = [(0.3, 0.2), (0.4, 0.2), (0.5, 0.2), (0.7, 0.2), (0.6, 0.2), (0.86, 0.2)]&lt;br /&gt;
# six points for a rectangle&lt;br /&gt;
#points = [(0.3, 0.2), (0.3, 0.4), (0.501, 0.4), (0.501, 0.2), (0.702, 0.4), (0.702, 0.2)]&lt;br /&gt;
&lt;br /&gt;
edges, center = centroid(points)&lt;br /&gt;
&lt;br /&gt;
# draw points&lt;br /&gt;
colors = cm.rainbow(np.linspace(0, 1, len(points)))&lt;br /&gt;
plot.scatter([i[0] for i in points], [i[1] for i in points], color=colors)&lt;br /&gt;
&lt;br /&gt;
# draw lines from centroid to points&lt;br /&gt;
plot.scatter(center[0], center[1], color='green')&lt;br /&gt;
for point in points:&lt;br /&gt;
    draw_arrow(axis, center, point, 'red', radius=0)&lt;br /&gt;
&lt;br /&gt;
# draw edges of shortest path&lt;br /&gt;
for i in range(len(edges)):&lt;br /&gt;
    draw_arrow(axis, edges[i][0], edges[i][1], 'black', radius=0.)&lt;br /&gt;
&lt;br /&gt;
plot.show()&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mvolodin</name></author>	</entry>

	</feed>