|
|
|
import getopt
|
|
|
|
import random
|
|
|
|
import sys
|
|
|
|
from typing import List
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
from scipy.spatial import ConvexHull
|
|
|
|
from scipy.spatial.qhull import QhullError
|
|
|
|
|
|
|
|
from kmeans.algorithms import k_means
|
|
|
|
from kmeans.clustering.cluster import Cluster
|
|
|
|
from kmeans.clustering.point import Point
|
|
|
|
|
|
|
|
|
|
|
|
def generate_points(x_bound: int, y_bound: int, count: int) -> List:
|
|
|
|
"""
|
|
|
|
Generates random points without replacement bounded by (x_bound, y_bound)
|
|
|
|
|
|
|
|
@param x_bound The x direction boundary.
|
|
|
|
@param y_bound The y direction boundary.
|
|
|
|
@param count The count of points.
|
|
|
|
"""
|
|
|
|
xs = random.sample(range(0, x_bound), count)
|
|
|
|
|
|
|
|
ys = random.sample(range(0, y_bound), count)
|
|
|
|
|
|
|
|
points = list(zip(xs, ys))
|
|
|
|
|
|
|
|
result = []
|
|
|
|
for p in points:
|
|
|
|
result.append(Point(p[0], p[1]))
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
try:
|
|
|
|
opts, args = getopt.getopt(sys.argv[1:], "x:y:r:",
|
|
|
|
['x=', 'y=', 'random='])
|
|
|
|
except getopt.GetoptError as err:
|
|
|
|
print('Option not recognized')
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
x = None
|
|
|
|
y = None
|
|
|
|
random = None
|
|
|
|
|
|
|
|
for o, a in opts:
|
|
|
|
if o in ('-x', '--x'):
|
|
|
|
x = int(a)
|
|
|
|
elif o in ('-y', '--y'):
|
|
|
|
y = int(a)
|
|
|
|
elif o in ('-r', '--random'):
|
|
|
|
random = int(a)
|
|
|
|
else:
|
|
|
|
print(f'Unknown option {o}\n')
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
if x is None or y is None or random is None:
|
|
|
|
print('x, y, and r must be specified\n')
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
points = generate_points(x, y, random)
|
|
|
|
|
|
|
|
print('--- INITIAL POINT PLOT ---')
|
|
|
|
xs = [p.x for p in points]
|
|
|
|
ys = [p.y for p in points]
|
|
|
|
plt.plot(xs, ys, 'o')
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
clusters = k_means(points, 4, 0.001)
|
|
|
|
|
|
|
|
# Color clusters
|
|
|
|
assigned_colors = plt.cm.gist_ncar(np.linspace(0, 1, 4))
|
|
|
|
|
|
|
|
for i, cluster in enumerate(clusters):
|
|
|
|
cluster.color = assigned_colors[i]
|
|
|
|
|
|
|
|
print('--- CLUSTER PLOT ---')
|
|
|
|
for cluster in clusters:
|
|
|
|
xs = [p.x for p in cluster.points]
|
|
|
|
ys = [p.y for p in cluster.points]
|
|
|
|
plt.plot(xs, ys, 'o', cluster.color)
|
|
|
|
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
print('--- CLUSTER PLOT WITH CONVEX HULL BOUNDARIES ---')
|
|
|
|
for cluster in clusters:
|
|
|
|
xs = [p.x for p in cluster.points]
|
|
|
|
ys = [p.y for p in cluster.points]
|
|
|
|
plt.plot(xs, ys, 'o', cluster.color)
|
|
|
|
|
|
|
|
# Convex hull plot
|
|
|
|
if len(cluster.points) >= 4:
|
|
|
|
points = np.array([p.array() for p in cluster.points])
|
|
|
|
|
|
|
|
try:
|
|
|
|
hull = ConvexHull(points)
|
|
|
|
except QhullError as e:
|
|
|
|
print(str(e))
|
|
|
|
continue
|
|
|
|
|
|
|
|
plt.plot(points[hull.vertices, 0],
|
|
|
|
points[hull.vertices, 1], 'r--', lw=2)
|
|
|
|
|
|
|
|
plt.plot(points[hull.vertices[0], 0],
|
|
|
|
points[hull.vertices[0], 1], 'ro')
|
|
|
|
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|