Skip to content

Commit 7981076

Browse files
committed
Initial fileset
1 parent 5721ee7 commit 7981076

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
//
2+
// K-Means.swift
3+
//
4+
// Created by John Gill on 2/25/16.
5+
6+
import Foundation
7+
8+
// Need a container to easily hold 2 Dimensional Vector2Ds
9+
class Vector2D: CustomStringConvertible {
10+
var x:Float = 0.0 // x-Coordinate of Vector2D
11+
var y:Float = 0.0 // y-Coordinate of Vector2D
12+
13+
init(x: Float, y: Float) {
14+
self.x = x
15+
self.y = y
16+
}
17+
18+
var description: String {
19+
return "Vector2D (\(self.x), \(self.y))"
20+
}
21+
}
22+
23+
// Ability to use std operators on Vector2D object
24+
func +(left: Vector2D, right: Vector2D) -> Vector2D {
25+
return Vector2D(x: left.x + right.x, y: left.y + right.y)
26+
}
27+
func +=(inout left: Vector2D, right: Vector2D) {
28+
left = left + right
29+
}
30+
func /(left:Vector2D, right: Float) -> Vector2D {
31+
return Vector2D(x: left.x / right, y: left.y / right)
32+
}
33+
func /=(inout left: Vector2D, right: Float) {
34+
left = left / right
35+
}
36+
37+
// TODO: Explain/Replace/Cleanup
38+
extension Array {
39+
var shuffle: [Element] {
40+
var elements = self
41+
for index in indices {
42+
let anotherIndex = Int(arc4random_uniform(UInt32(elements.count - index))) + index
43+
anotherIndex != index ? swap(&elements[index], &elements[anotherIndex]) : ()
44+
}
45+
return elements
46+
}
47+
func choose(n: Int) -> [Element] {
48+
return Array(shuffle.prefix(n))
49+
}
50+
}
51+
52+
// Calculates the Euclidean distance between two Vector2Ds
53+
func euclidean(v1:Vector2D, v2:Vector2D) -> Float {
54+
return sqrt(pow((v1.x - v2.x), 2.0) + pow((v1.y - v2.y), 2.0))
55+
}
56+
57+
// Get the INDEX of nearest Center to X
58+
func nearestCenter(x: Vector2D, Centers: [Vector2D]) -> Int {
59+
var nearestDist = FLT_MAX
60+
var minIndex:Int = 0;
61+
// Calculate the distance from Vector2D X to all the centers
62+
for (idx, c) in Centers.enumerate() {
63+
let dist = euclidean(x, v2: c)
64+
if dist < nearestDist {
65+
minIndex = idx
66+
nearestDist = dist
67+
}
68+
}
69+
return minIndex
70+
}
71+
72+
func kNN(numCenters: Int, convergeDist: Float, points: [Vector2D]) -> [Vector2D] {
73+
var centerMoveDist:Float = 0.0
74+
75+
// 1. Choose k Random Vector2Ds as the initial centers
76+
var kCenters:[Vector2D] = points.choose(numCenters)
77+
78+
// do following steps until convergence
79+
repeat {
80+
var cnts = [Float](count: numCenters, repeatedValue: 0.0)
81+
var nCenters = [Vector2D](count:numCenters, repeatedValue: Vector2D(x:0, y:0))
82+
// 2. Assign Vector2Ds to centers
83+
// a. Determine which center each Vector2D is closest to
84+
// b. Record how many Vector2Ds are assigned to each center
85+
for p in points {
86+
let c = nearestCenter(p, Centers: kCenters)
87+
cnts[c]++
88+
nCenters[c] += p
89+
}
90+
// 3. Calculate a new centers
91+
for idx in 0..<numCenters {
92+
nCenters[idx] /= cnts[idx]
93+
}
94+
// 4. Determine how far centers moved
95+
centerMoveDist = 0.0
96+
for idx in 0..<numCenters {
97+
centerMoveDist += euclidean(kCenters[idx], v2: nCenters[idx])
98+
}
99+
// 5. Update centers to the newly calculated ones
100+
kCenters = nCenters
101+
print("Complete iteration coverge(\(centerMoveDist) <? \(convergeDist))")
102+
} while(centerMoveDist > convergeDist)
103+
return kCenters
104+
}
105+
var points = [Vector2D]()
106+
let lim = 50
107+
for _ in 0..<lim {
108+
let x = Float(arc4random_uniform(UInt32(lim)))
109+
let y = Float(arc4random_uniform(UInt32(lim)))
110+
points.append(Vector2D(x: Float(x), y: y))
111+
}
112+
113+
print("\nCenters")
114+
for c in kNN(10, convergeDist: 0.1, points: points) {
115+
print(c)
116+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='osx'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Timeline
3+
version = "3.0">
4+
<TimelineItems>
5+
</TimelineItems>
6+
</Timeline>

K-Means/README.md

Whitespace-only changes.

0 commit comments

Comments
 (0)