Showing preview only (4,135K chars total). Download the full file or copy to clipboard to get everything.
Repository: andreaferretti/kmeans
Branch: master
Commit: a6c7107efa0d
Files: 137
Total size: 3.9 MB
Directory structure:
gitextract_bwhds1og/
├── .gitignore
├── Pharo4.0/
│ └── KMeans.st
├── README.md
├── c/
│ ├── compile.sh
│ ├── hashmap.c
│ ├── hashmap.h
│ ├── kmeans.c
│ ├── kmeans.h
│ ├── main.c
│ ├── point.c
│ └── point.h
├── chapel/
│ ├── .gitignore
│ ├── Makefile
│ └── main.chpl
├── clojure/
│ ├── project.clj
│ └── src/
│ └── clj/
│ └── kmeans/
│ ├── algo.clj
│ └── benchmark.clj
├── cpp/
│ ├── .gitignore
│ ├── Point.cpp
│ ├── Point.h
│ ├── benchmark.cpp
│ ├── biicode.conf
│ ├── kmeans.cpp
│ └── kmeans.h
├── crystal/
│ ├── .gitignore
│ └── kmeans.cr
├── cuda/
│ ├── CMakeLists.txt
│ └── src/
│ ├── config.h
│ ├── kmeans.cu
│ ├── kmeans.h
│ ├── main.cu
│ ├── point.cu
│ └── point.h
├── d/
│ └── main.d
├── elixir/
│ ├── kmeans.ex
│ └── main.exs
├── erlang/
│ ├── kmeans.erl
│ └── main.erl
├── factor/
│ └── kmeans/
│ ├── benchmark/
│ │ └── benchmark.factor
│ └── kmeans.factor
├── fsharp/
│ ├── .gitignore
│ ├── Makefile
│ ├── kmeans.fs
│ ├── main.fs
│ └── paket.dependencies
├── go/
│ ├── .gitignore
│ └── main.go
├── haskell/
│ ├── Kmeans.hs
│ ├── Main.hs
│ ├── Point.hs
│ ├── Setup.hs
│ └── kmeans.cabal
├── java/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ ├── Entry.java
│ ├── KMeans.java
│ └── Point.java
├── java8/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── example/
│ ├── KMeans.java
│ ├── Main.java
│ └── Point.java
├── julia/
│ └── kmeans.jl
├── kotlin/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── kmeans.kt
├── lisp/
│ ├── kmeans.lisp
│ └── readme.txt
├── lua/
│ └── kmeans.lua
├── nim/
│ ├── algo.nim
│ └── benchmark.nim
├── node/
│ ├── kmeans.js
│ └── package.json
├── ocaml/
│ ├── kmeans.ml
│ ├── kmeans.mli
│ ├── main.ml
│ └── point.ml
├── opencl/
│ ├── .gitignore
│ ├── kmeans.cl
│ ├── kmeans.nim
│ ├── kmeans.nimble
│ ├── point.h
│ ├── point.nim
│ └── util.nim
├── openmp/
│ ├── compile.sh
│ ├── makefile
│ └── src/
│ ├── config.h
│ ├── kmeans.c
│ ├── kmeans.h
│ ├── main.c
│ ├── point.c
│ └── point.h
├── parasail/
│ ├── benchmark.psl
│ ├── kmeans.psl
│ └── point.psl
├── perl/
│ └── kmeans.pl
├── pharo3/
│ └── KMeans.st
├── points.json
├── pony/
│ ├── .gitignore
│ ├── Makefile
│ └── kmeans/
│ └── main.pony
├── python/
│ └── kmeans.py
├── results
├── ruby/
│ └── kmeans.rb
├── rust/
│ ├── .gitignore
│ ├── Cargo.toml
│ └── src/
│ ├── algo.rs
│ ├── lib.rs
│ ├── main.rs
│ └── point.rs
├── scala/
│ ├── build.sbt
│ └── src/
│ └── main/
│ └── scala/
│ └── kmeans/
│ ├── Algo.scala
│ └── Main.scala
├── scala-js/
│ ├── .gitignore
│ ├── build.sbt
│ ├── project/
│ │ ├── build.properties
│ │ └── plugins.sbt
│ └── src/
│ └── main/
│ └── scala/
│ └── kmeans/
│ ├── Algo.scala
│ └── Main.scala
├── scala-native/
│ ├── build.sbt
│ ├── project/
│ │ ├── build.properties
│ │ └── plugins.sbt
│ └── src/
│ └── main/
│ └── scala/
│ └── kmeans/
│ ├── Algo.scala
│ ├── Main.scala
│ └── native.scala
├── stanza/
│ ├── compile.sh
│ ├── kmeans.stanza
│ └── kmeansutils.c
├── swift/
│ ├── .gitignore
│ ├── kmeans.swift
│ └── main.swift
└── x10/
├── CJson.x10
├── KMeans.x10
├── Main.x10
├── Makefile
├── RichPoint.x10
├── javalib/
│ └── jackson-core-2.5.1.jar
├── jsonRead.cc
├── jsonRead.h
└── jsonRead.java
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
cuda/build/*
cuda/.metadata
cuda/RemoteSystemsTempFiles
cuda/kmeans.out*
cuda/CMakeCache.txt
cuda/CMakeFiles/
cuda/Makefile
cuda/cmake_install.cmake
openmp/kmeans.out*
openmp/build/*
.cproject
.project
scala/target
scala/project/project
scala/project/target
scala-native/target
scala-native/project/project
scala-native/project/target
rust/target
node/node_modules
clojure/target
.lein-repl-history
nimcache
/nim/benchmark
*.psl.o
*.psl.s
parasail/benchmark
errors.err
erlang/*.beam
elixir/*.beam
java/target
java/project
java8/target
ocaml/_build
ocaml/*.byte
ocaml/*.native
kotlin/target
lua/dkjson.lua
c/*.o
c/kmeans
haskell/.cabal-sandbox
haskell/dist
haskell/cabal.sandbox.config
d/main
d/main.o
x10/cbin
x10/javabin
x10/javalib/jsonRead.jar
================================================
FILE: Pharo4.0/KMeans.st
================================================
Object subclass: #KMeans
instanceVariableNames: 'iterations clusters'
classVariableNames: ''
poolDictionaries: ''
category: 'KMeans'!
!KMeans commentStamp: 'RoelWuyts 3/31/2016 09:37' prior: 0!
I implement an idiomatic version of the kmeans algorithm in order to compare to implementations in other languages - see https://github.com/andreaferretti/kmeans .
To use me:
- download Pharo and launch an image.
- put the points.json in the same directory than the image.
- type "KMeans benchmark: 100" (in the Playground or anywhere else),
- select the text and 'Print it' in the contextual menu.
- wait...!
!KMeans methodsFor: 'algorithm' stamp: 'AndreaFerretti 10/8/2014 18:57'!
run: points
| centroids |
centroids := points first: clusters.
iterations timesRepeat: [
centroids := (self cluster: points around: centroids) collect: [ :each | each average ]
].
^ self cluster: points around: centroids! !
!KMeans methodsFor: 'algorithm' stamp: 'RoelWuyts 3/1/2016 09:51'!
cluster: points around: centroids
^ (points groupedBy: [ :p | p closestFrom: centroids ]) values! !
!KMeans methodsFor: 'algorithm' stamp: 'AndreaFerretti 10/8/2014 19:01'!
run: points times: times
times timesRepeat: [ self run: points ].! !
!KMeans methodsFor: 'benchmarks' stamp: 'AndreaFerretti 10/8/2014 19:03'!
benchmark: points repeating: repetitions
| time |
time := Time millisecondsToRun: [ self run: points times: repetitions ].
^ time / repetitions.! !
!KMeans methodsFor: 'initialization' stamp: 'RoelWuyts 2/29/2016 17:07'!
clusters: numClusters iterations: numIterations
iterations := numIterations.
clusters := numClusters! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
KMeans class
instanceVariableNames: ''!
!KMeans class methodsFor: 'benchmarks' stamp: 'RoelWuyts 3/31/2016 09:24'!
benchmark: repetitions pointsFilename: pointsFilename
"self benchmark: 100 pointsFilename: 'points.json' "
| fileref str points |
fileref := pointsFilename asFileReference.
str := FileStream readOnlyFileNamed: fileref.
points := (MCFileTreeJsonParser parseStream: str) collect: [:arr | Point x: arr first y: arr second ].
^(self clusters: 10 iterations: 15)
benchmark: points repeating: repetitions! !
!KMeans class methodsFor: 'benchmarks' stamp: 'RoelWuyts 3/31/2016 09:25'!
benchmark: repetitions
"self benchmark: 100"
^self benchmark: repetitions pointsFilename: self pointsFilename ! !
!KMeans class methodsFor: 'benchmarks' stamp: 'RoelWuyts 3/31/2016 09:23'!
pointsFilename
"The name and location of the file that contains the points used for the benchmarking."
"By default it is assumed to be next to your Pharo image."
^'points.json'! !
!KMeans class methodsFor: 'instance creation' stamp: 'RoelWuyts 2/29/2016 17:09'!
clusters: numClusters iterations: numIterations
^self new clusters: numClusters iterations: numIterations! !
'From Pharo4.0 of 18 March 2013 [Latest update: #40626] on 31 March 2016 at 9:37:42.371164 am'!
!Point methodsFor: '*KMeans' stamp: 'RoelWuyts 3/1/2016 09:57'!
closestFrom: points
^ points detectMin: [:p | self dist: p ]! !
================================================
FILE: README.md
================================================
This benchmark is born to compare the performance of Pharo 3 in executing a simple machine learning algorithm with a reference implementation in Python and Scala. Since then, it got a little out of hand, and a few other implementations are available.
**This benchmark is not going to be updated anymore after 30/3/2017. I don't have the time to reinstall all languages on the original machine. Still, you can play with it and test everything on your computer. Thus, I will not accept any more PRs to this repository.**
Rules
=====
The implementations should all follow the same algorithm, and be optimized for idiomatic code and not for speed. The example is intended to compare time of execution for a typical machine learning algorithm, ideally during an interactive session, instead of highly optimized production code. As such, it is important that the code is straightforward and that there is no separate phase to prepare the caches.
The points are in `points.json`, and are to be grouped into 10 clusters, using 15 iterations of kmeans. The initial centroids are initialized to the first 10 points, and we take an average over 100 runs.
Results
=======
Time for running on my laptop are available under `results`. A few surprises:
* Writing a working Rust implementation was surprisingly difficult; writing one that would perform decently even more so. I had to rely frequently on help from people online.
* PyPy is able to outperform Scala
* Factor is pretty impressive, given that it is a fairly small project with a dedicated VM. With an implementation in 8 (!) lines, we get the a fairly performing dynamic language
* Nim was also quite impressive: my first implementation was as easy as Python, and it was just behind Rust; when an unnecessary copy was removed, it turned out to be the fastest.
Contribute
==========
If you want to contribute an implementation in a different language, please file a PR. Try to follow the same logic that is used in the examples in other languages - for instance, using a group by operation where available. As you may notice, the algorithm is not optimized, and intentionally so: while K-means in particular has various possible optimizations, other similar algorithms may fail to have the particular shape that makes these optimizations viable.
For the curious folks, I have tried a more optimized (single-threaded) implementation in Nim, that avoids the square root in the distance and accumulates the sum of points near a centroid, rather than putting them into a data structure. For comparison, this version runs in 67 ms. Computers are actually quite fast, these days!
How to run
==========
**C**
sudo apt-get install libglib2.0-0
sudo apt-get install libjansson-dev # or equivalent for your OS
./compile.sh
./kmeans
**C++**
We use [BiiCode](https://www.biicode.com/) for building. Assuming you have it installed, from the `cpp` directory do
bii init -L
bii configure -DCMAKE_BUILD_TYPE=RELEASE
bii build
bin/user_cpp_benchmark
**Chapel**
Before compiling chapel please do:
export CHPL_LLVM=llvm
to enable LLVM support (this is used for the json import in C). Then, make sure that `chpl` is on your `$PATH` (for instance with `source source util/setchplenv.sh`). Finally:
make
./kmeans
**Clojure**: `lein with-profile uberjar run`
**Common Lisp**: `sbcl --script kmeans.lisp`
**Crystal**:
crystal build kmeans.cr --release
./kmeans
**CUDA**
sudo apt-get install libjansson-dev # or equivalent for your OS (e.g. on Mac you can: brew install jansson)
cmake .
make
then
./kmeans.out [ input_file.json number_of_points number_of_centroids ]
**D**:
dmd -O -inline -release -noboundscheck main.d
./main
**Elixir**:
elixirc kmeans.ex
elixir main.exs
**Erlang**:
erl
1> c(main).
2> c(kmeans).
3> main:run().
**F#**:
make
make run
**Factor**:
USE: kmeans.benchmark
100 "../points.json" kmeans-benchmark
**Go**
go build main.go
./main
**Haskell**:
cabal install --only-dependencies
cabal build
dist/build/kmeans/kmeans
**Java**:
mvn compile
mvn exec:java
**Java 8 (Streams and Lambdas)**:
mvn compile
mvn exec:java
**Julia**:
julia -e 'Pkg.add("JSON")'
julia kmeans.jl
**Kotlin**:
mvn compile exec:java
**Lua**: download [this JSON library](http://dkolf.de/src/dkjson-lua.fsl/home) and put it in the same folder as the main file. Then run
lua kmeans.lua
luajit kmeans.lua
**Nim**:
nim c -d:release benchmark
./benchmark
**Node**:
npm install
node kmeans.js
**OCaml**:
opam install core yojson
corebuild -pkg yojson main.native
./main.native
**OpenCL**: need to have Nim and Nimble installed, as well as a NVIDIA GPU.
Check the library paths in `kmeans.nimble`, then run `nimble kmeans`.
**OpenMP**
make
./kmeans.out [ inputfile.json number_of_points number_of_centroids number_of_threads ]
or:
./kmeans.out [number_of_threads]
**Parasail**: assume `pslc.csh` is on `$PATH`. Then
pslc.csh -O3 point.psl kmeans.psl benchmark.psl -o benchmark
./benchmark
**Perl**:
perl kmeans.pl
**Pharo3**: install `NeoJSON` and file-in `Kmeans.st`, then open a workspace and write something like
| path points kmeans |
path := '../points.json'.
kmeans := KMeans new
iterations: 15;
clusters: 10;
yourself.
StandardFileStream readOnlyFileNamed: path
do: [ :stream |
points := (NeoJSONReader on: stream) next collect: [ :each |
(each first) @ (each second)
].
].
kmeans benchmark: points repeating: 100
**Python**:
python kmeans.py
pypy kmeans.py
**Pony**:
make
make run
**Ruby**:
ruby kmeans.rb
rbx kmeans.rb
**Rust**:
cargo run --release
**Scala**: `sbt run`
**Scala-Js**:
First, generate the compiled javascript with `sbt fullOptJS`. Then,
`cd target/scala-2.11`, open `node` and
> require('./kmeans-opt')
> require('./kmeans-launcher')
At first, it seems that nothing is going on, but after a while you should see
the results printed.
**Scala-Native**: `sbt run`
**Stanza**:
Install Stanza following instructions [here](http://lbstanza.org/chapter1.html#anchor1) and put it into your PATH.
./compile.sh
./kmeans
**Swift**:
swiftc -Ounchecked kmeans.swift main.swift
./main
**X10**: First
mkdir cbin
mkdir javabin
Make sure that the `bin` folder of X10 is on your path. Then, for the Java target, decomment lines with `Java json import` inside `Main.x10` and
make java
make runJava
For the native target, decomment lines with `C json import` inside `Main.x10` and
make c
make runC
================================================
FILE: c/compile.sh
================================================
gcc -Wall -O3 -c hashmap.c -o hashmap.o `pkg-config --cflags --libs glib-2.0`
gcc -Wall -O3 -c kmeans.c -o kmeans.o
gcc -Wall -O3 -c main.c -o main.o
gcc -Wall -O3 -c point.c -o point.o
g++ -o kmeans hashmap.o kmeans.o main.o point.o `pkg-config --cflags --libs glib-2.0` -s -ljansson
================================================
FILE: c/hashmap.c
================================================
#include <stdlib.h>
#include <stdio.h>
#include"hashmap.h"
#include<string.h>
#include <glib.h>
GHashTable* hash = NULL;
void insert(Point* pkey, Point* pelem)
{
if (!hash) {
hash = g_hash_table_new(NULL,NULL);
}
PointArray* pa = g_hash_table_lookup (hash, pkey);
if (pa) {
pa->points[pa->size].x = pelem->x;
pa->points[pa->size].y = pelem->y;
pa->size += 1;
//g_hash_table_replace(hash, pkey, pa);
} else {
PointArray* pa = (PointArray*)malloc(sizeof(PointArray));
pa->size = 1;
pa->points[0].x = pelem->x;
pa->points[0].y = pelem->y;
g_hash_table_insert(hash, pkey, pa);
}
}
int i=0;
void iterator(gpointer key, gpointer value, gpointer ret) {
memcpy(&(((Clusters*)ret)->groups[i]), value , sizeof(PointArray));
i++;
}
void setCluster(Clusters* ret) {
i=0;
g_hash_table_foreach(hash, (GHFunc)iterator, ret);
g_hash_table_destroy(hash);
hash = NULL;
}
================================================
FILE: c/hashmap.h
================================================
#ifndef HASHMAP_H_INCLUDED
#define HASHMAP_H_INCLUDED
#include"point.h"
#include"kmeans.h"
void insert(Point* key, Point* elem);
void printHashMap();
void setCluster(Clusters* ret);
#endif // HASHMAP_H_INCLUDED
================================================
FILE: c/kmeans.c
================================================
#include <stdio.h>
#include <stdlib.h>
#include"kmeans.h"
#include"point.h"
#include"hashmap.h"
int n = 10;
int iters = 15;
const long points_number = 100000;
double dist(Point* p1, Point* p2)
{
Point p = {p1->x, p1->y};
sub(&p, p2);
double result = modulus(&p);
return result;
}
void average(PointArray* xs, Point* ret)
{
long i;
ret->x = xs->points[0].x;
ret->y = xs->points[0].y;
for (i=1;i<xs->size;i++)
{
add(ret, &(xs->points[i]));
}
divide(ret, xs->size);
return;
}
long closest(Point* p, PointArray* choices)
{
long i;
double minVal = dist(p, &(choices->points[0]));
long min = 0;
for (i=1;i<choices->size;i++)
{
double actualDist = dist(p, &(choices->points[i]));
if (actualDist < minVal) {
min = i;
minVal = actualDist;
}
}
return min;
}
void calcClusters(PointArray* xs, Clusters* clusters, PointArray* centroids)
{
long i = 0;
long theClosest = 0;
clusters->size = 10;
for (i=0;i<10;i++)
clusters->groups[i].size = 0;
for (i=0;i<xs->size;i++) {
//printf("punto %d",i);
theClosest = closest(&(xs->points[i]), centroids);
insert(&(xs->points[theClosest]), &(xs->points[i]));
}
setCluster(clusters);
return;
}
void run(PointArray* xs, Clusters* clusters)
{
long i,k;
Point* temp = malloc(sizeof(Point));
PointArray* centroids = (PointArray*)malloc(sizeof(PointArray));
centroids->size = n;
for (i=0;i<n;i++) {
centroids->points[i].x = xs->points[i].x;
centroids->points[i].y = xs->points[i].y;
}
clusters->size = iters;
for (k=0;k<iters;k++) {
calcClusters(xs, clusters, centroids);
for (i=0;i<n;i++) {
average(&(clusters->groups[i]), temp);
centroids->points[i].x = temp->x;
centroids->points[i].y = temp->y;
}
}
free(temp);
free(centroids);
return;
}
================================================
FILE: c/kmeans.h
================================================
#ifndef KMEANS_H_INCLUDED
#define KMEANS_H_INCLUDED
#include"point.h"
typedef struct {
long size;
Point points[100000];
} PointArray;
typedef struct {
long size;
PointArray groups[10];
} Clusters;
void run(PointArray* xs, Clusters* clusters);
#endif // KMEANS_H_INCLUDED
================================================
FILE: c/main.c
================================================
#include <stdio.h>
#include <stdlib.h>
#include"point.h"
#include"hashmap.h"
#include <string.h>
#include <jansson.h>
#include <sys/time.h>
int times = 100;
long int getTime(PointArray* xs, Clusters* clusters) {
int i=0;
struct timeval tval_before, tval_after, tval_result;
gettimeofday(&tval_before, NULL);
for (i=0;i<times;i++) {
run(xs, clusters);
}
gettimeofday(&tval_after, NULL);
timersub(&tval_after, &tval_before, &tval_result);
long int ms = ((long int)tval_result.tv_sec*1000) + ((long int)tval_result.tv_usec/1000);
return ms;
}
int main()
{
json_t *json;
json_error_t error;
size_t index;
long int temp = 0;
json_t *value;
PointArray* xs = (PointArray*)malloc(sizeof(PointArray));
xs->size = 100000;
json = json_load_file("../points.json", 0, &error);
if(!json) {
printf("Error parsing Json file");
fflush(stdout);
return -1;
}
json_array_foreach(json, index, value) {
double x = json_number_value(json_array_get(value,0));
double y = json_number_value(json_array_get(value,1));
xs->points[index].x = x;
xs->points[index].y = y;
}
Clusters* clusters = (Clusters*)malloc(sizeof(Clusters));
temp += getTime(xs, clusters);
printf("Average Time: %li ms\n", (temp/times));
return 0;
}
================================================
FILE: c/point.c
================================================
#include<math.h>
#include"point.h"
#include <stdlib.h>
#include <stdio.h>
void divide(Point* p, long d)
{
p->x = p->x/((double)d);
p->y = p->y/((double)d);
return;
}
void add(Point* p1, Point* p2)
{
p1->x = p1->x+p2->x;
p1->y = p1->y+p2->y;
return;
}
void sub(Point* p1, Point* p2)
{
p1->x = p1->x-p2->x;
p1->y = p1->y-p2->y;
return;
}
double sq(double x)
{
return x*x;
}
double modulus(Point* p)
{
return sqrt(sq(p->x)+ sq(p->y));
}
================================================
FILE: c/point.h
================================================
#ifndef POINT_H_INCLUDED
#define POINT_H_INCLUDED
typedef struct {
double x;
double y;
} Point;
void divide(Point* p, long d);
void add(Point* p1, Point* p2);
void sub(Point* p1, Point* p2);
double sq(double x);
double modulus(Point* p);
#endif // POINT_H_INCLUDED
================================================
FILE: chapel/.gitignore
================================================
kmeans
================================================
FILE: chapel/Makefile
================================================
MAKEFLAGS = --no-print-directory
CHPL = chpl
TARGETS = \
default: all
clean: FORCE
rm -f kmeans
all:
$(CHPL) --fast-followers --fast -optimize --specialize --local --no-checks --no-debug --optimize-loop-iterators --optimize-on-clauses --main-module main -o kmeans jansson.h -ljansson main.chpl
FORCE:
================================================
FILE: chapel/main.chpl
================================================
const n: int = 10;
const iters: int = 15;
const executions: int = 100;
class point {
var x: real;
var y: real;
proc divide(d: real) {
this.x = x/d;
this.y = y/d;
return;
}
proc add(p2: point) {
this.x = this.x+p2.x;
this.y = this.y+p2.y;
return;
}
proc sub(p2: point) {
this.x = this.x-p2.x;
this.y = this.y-p2.y;
return;
}
proc modulus() {
return sqrt(sq(x)+sq(y));
}
}
class closestPoint : ReduceScanOp {
type eltType;
var min : point;
var minDist: real = max(real);
proc accumulate((val, p): (point, point)) {
var actualDist = dist(p, val);
if (actualDist < minDist) {
minDist = actualDist;
min = val;
}
}
proc combine(other: closestPoint){
if (this.minDist > other.minDist) {
this.min = other.min;
this.minDist = other.minDist;
}
}
proc generate(){
return min;
}
}
proc sq(x: real) {
return x*x;
}
proc dist(p1: point, p2: point) {
var tmp: point = new point(p1.x, p1.y);
tmp.sub(p2);
var result = tmp.modulus();
delete(tmp);
return result;
}
proc average(ps: domain(point)): point {
var sum: point = new point(0,0);
forall e in ps do
sum.add(e);
sum.divide(ps.size);
return sum;
}
proc closest(rp: point, choices: [] point): point {
//Cannot use a reduce operator instatiating it with a parameter?
return closestPoint reduce forall x in choices do (x,rp);
}
proc clusters(xs: [] point, centroids: [] point) {
//too tricky hashmap construction...
type PointArr = domain(point);
var keys: domain(point);
var hashMap: [keys] PointArr;
forall c in centroids do
keys += c;
forall x in xs do
hashMap(closest(x, centroids)) += x;
var result: [1..centroids.size] PointArr;
forall i in 1..centroids.size do {
result[i] += hashMap(centroids(i));
}
return result;
}
var centroids: [1..n] point;
var xs: [1..100000] point;
C.getJson();
for i in 1..100000 do
xs[i] = new point(C.getXAt(i), C.getYAt(i));
use Time;
var timer = new Timer();
timer.clear();
timer.start();
for k in 1..executions do {
forall j in 1..n do {
delete(centroids[j]);
centroids[j] = new point(xs[j].x, xs[j].y);
}
for i in 1..iters do {
var clus = clusters(xs, centroids);
forall c in [1..n] do {
centroids[c] = average(clus[c]);
}
}
}
timer.stop();
var elapsedTime = timer.elapsed(TimeUnits.milliseconds);
writeln("Last centroids are:");
for c in centroids do
writeln(c);
writeln("Elapsed time is ", (elapsedTime/executions));
module C {
extern {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jansson.h>
static double cxs[100000];
static double cys[100000];
static void getJson() {
int i=0;
json_t *json;
json_error_t error;
size_t index;
long int temp = 0;
json_t *value;
json = json_load_file("../points.json", 0, &error);
if(!json) {
printf("Error parsing Json file");
fflush(stdout);
return;
}
json_array_foreach(json, index, value) {
double x = json_number_value(json_array_get(value,0));
double y = json_number_value(json_array_get(value,1));
cxs[index] = x;
cys[index] = y;
}
return;
}
static double getXAt(long i) {
return cxs[i-1];
}
static double getYAt(long i) {
return cys[i-1];
}
}
}
================================================
FILE: clojure/project.clj
================================================
(defproject kmeans "0.1.0"
:description "Kmeans benchmark"
:dependencies [
[org.clojure/clojure "1.7.0"]
[cheshire "5.3.1"]]
:source-paths ["src/clj"]
:main kmeans.benchmark)
================================================
FILE: clojure/src/clj/kmeans/algo.clj
================================================
(ns kmeans.algo)
(defn sq [x] (* x x))
(defn v- [[a b] [c d]]
[(- a c) (- b d)])
(defn v+ [[a b] [c d]]
[(+ a c) (+ b d)])
(defn vdiv [[a b] k]
[(/ a k) (/ b k)])
(defn norm [[a b]]
(Math/sqrt (+ (sq a) (sq b))))
(defn dist [v w] (norm (v- v w)))
(defn closest [x choices]
(apply min-key #(dist x %) choices))
(defn avg [xs]
(vdiv
(reduce v+ xs)
(count xs)))
(defn clusters [xs centroids]
(vals (group-by #(closest % centroids) xs)))
(defn run [points n iters]
(let
[centroids-seq (iterate
(fn [centroids]
(map avg (clusters points centroids)))
(take n points))
final-centroids (nth centroids-seq iters)]
(clusters points final-centroids)))
================================================
FILE: clojure/src/clj/kmeans/benchmark.clj
================================================
(ns kmeans.benchmark
(:require
[clojure.java.io :as io]
[cheshire.core :as json])
(:use [kmeans.algo]))
(defn now []
(.getTime (java.util.Date.)))
(defn result [ms iters]
(println (str "The average time was " (/ (float ms) iters) " ms")))
(defn read-points [path]
(json/parse-stream (io/reader path) true))
(defn -main
[& args]
(let [
n 10
iters 15
repeated 100
points (read-points "../points.json")
start (now)
]
(dotimes [_ repeated] (run points n iters))
(result (- (now) start) repeated)
))
================================================
FILE: cpp/.gitignore
================================================
/bii
/bin
================================================
FILE: cpp/Point.cpp
================================================
#include <math.h>
#include "Point.h"
using std::cout;
using std::ostream;
using std::hash;
using std::size_t;
Point::Point() {}
Point::Point(double x_, double y_) {
x = x_;
y = y_;
}
bool Point::operator==(const Point& q) const {
return (x == q.x) && (y == q.y);
}
Point Point::operator+(const Point& q) const {
return Point(x + q.x, y + q.y);
}
Point Point::operator-(const Point& q) const {
return Point(x - q.x, y - q.y);
}
Point Point::operator/(double k) const {
return Point(x / k, y / k);
}
double Point::norm() const {
return sqrt(x * x + y * y);
}
bool Point::operator<(const Point& q) const {
if (x != q.x) {
return x < q.x;
} else {
return y < q.y;
}
}
double dist(const Point& p, const Point& q) {
return (p - q).norm();
}
ostream& operator<<(ostream& os, const Point& p) {
os << "(" << p.x << ", " << p.y << ")";
}
================================================
FILE: cpp/Point.h
================================================
#ifndef GUARD_Point
#define GUARD_Point
#include <iostream>
class Point {
public:
double x, y;
Point();
Point(double x_, double y_);
Point operator+(const Point& q) const;
Point operator-(const Point& q) const;
Point operator/(double k) const;
double norm() const;
bool operator==(const Point& q) const;
bool operator<(const Point& q) const;
friend std::ostream& operator<<(std::ostream& os, const Point& p);
};
double dist(const Point& p, const Point& q);
namespace std {
template <>
struct hash<Point> {
size_t operator()(const Point& p) const {
return hash<double>()(p.x) ^ (hash<double>()(p.y) << 1);
}
};
}
#endif
================================================
FILE: cpp/benchmark.cpp
================================================
#include <string>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <stdexcept>
#include <chrono>
#include "json11/json11.hpp"
#include "Point.h"
#include "kmeans.h"
using std::string;
using std::cout;
using std::endl;
using std::vector;
using std::domain_error;
using std::ifstream;
using std::chrono::steady_clock;
using json11::Json;
Point read_point(const Json& json) {
if (json.is_array()) {
auto coords = json.array_items();
return Point(coords[0].number_value(), coords[1].number_value());
}
throw domain_error("Invalid JSON");
}
vector<Point> read_points(const string& path) {
if (ifstream infile{path}) {
const string contents{std::istreambuf_iterator<char>(infile), {}};
string error;
auto json = Json::parse(contents, error);
auto items = json.array_items();
vector<Point> result;
transform(items.begin(), items.end(), back_inserter(result), read_point);
return result;
}
throw domain_error("Invalid JSON");
}
int main() {
const int n = 10;
const int iters = 15;
const int repeat = 100;
auto points = read_points("../points.json");
steady_clock::time_point begin = steady_clock::now();
for (int i = 0; i < repeat; i++) {
auto centroids = kmeans(points, n, iters);
}
steady_clock::time_point end = steady_clock::now();
int millis = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
int average = millis / repeat;
cout << "Average running time = " << average << " ms" << std::endl;
return 0;
}
================================================
FILE: cpp/biicode.conf
================================================
# Biicode configuration file
[requirements]
lasote/json11: 4
[parent]
# The parent version of this block. Must match folder name. E.g.
# user/block # No version number means not published yet
# You can change it to publish to a different track, and change version, e.g.
# user/block(track): 7
[paths]
# Local directories to look for headers (within block)
# /
# include
[dependencies]
# Manual adjust file implicit dependencies, add (+), remove (-), or overwrite (=)
# hello.h + hello_imp.cpp hello_imp2.cpp
# *.h + *.cpp
[mains]
# Manual adjust of files that define an executable
# !main.cpp # Do not build executable from this file
# main2.cpp # Build it (it doesnt have a main() function, but maybe it includes it)
[tests]
# Manual adjust of files that define a CTest test
# test/* pattern to evaluate this test/ folder sources like tests
[hooks]
# These are defined equal to [dependencies],files names matching bii*stage*hook.py
# will be launched as python scripts at stage = {post_process, clean}
# CMakeLists.txt + bii/my_post_process1_hook.py bii_clean_hook.py
[includes]
# Mapping of include patterns to external blocks
# hello*.h: user3/depblock # includes will be processed as user3/depblock/hello*.h
json11/*.hpp: lasote
[data]
# Manually define data files dependencies, that will be copied to bin for execution
# By default they are copied to bin/user/block/... which should be taken into account
# when loading from disk such data
# image.cpp + image.jpg # code should write open("user/block/image.jpg")
================================================
FILE: cpp/kmeans.cpp
================================================
#include <numeric>
#include <limits>
#include <unordered_map>
#include <vector>
#include "kmeans.h"
using std::vector;
using std::unordered_map;
Point average(const vector<Point>& v) {
return accumulate(v.begin(), v.end(), Point(0.0, 0.0)) / v.size();
}
Point closest(Point p, const vector<Point>& centroids) {
double minDist = std::numeric_limits<double>::max();
Point result;
for (const auto& c : centroids) {
auto d = dist(p, c);
if (d < minDist) {
minDist = d;
result = c;
}
}
return result;
}
unordered_map<Point, vector<Point>> group_by(const vector<Point>& points, const vector<Point>& centroids) {
unordered_map<Point, vector<Point>> groups;
for (const auto& p : points) {
groups[closest(p, centroids)].push_back(p);
}
return groups;
}
void update_centroids(const vector<Point>& points, vector<Point>& centroids) {
auto groups = group_by(points, centroids);
int i = 0;
for (const auto& g : groups) {
centroids[i] = average(g.second);
++i;
}
}
vector<Point> kmeans(const vector<Point>& points, int n, int iterations) {
vector<Point> centroids(points.begin(), points.begin() + n);
for (int i = 0; i < iterations; i++) {
update_centroids(points, centroids);
}
return centroids;
}
================================================
FILE: cpp/kmeans.h
================================================
#ifndef GUARD_Kmeans
#define GUARD_Kmeans
#include <vector>
#include "Point.h"
std::vector<Point> kmeans(const std::vector<Point>& points, int n, int iterations);
#endif
================================================
FILE: crystal/.gitignore
================================================
/kmeans
================================================
FILE: crystal/kmeans.cr
================================================
require "json"
N = 10
ITERS = 15
struct Point
getter x, y
def initialize(@x : Float64, @y : Float64)
end
def +(p : Point)
Point.new @x + p.x, @y + p.y
end
def -(p : Point)
Point.new @x - p.x, @y - p.y
end
def /(d)
Point.new @x / d, @y / d
end
def modulus
Math.sqrt(sq(@x) + sq(@y))
end
end
def sq(d : Float64)
d * d
end
def dist(x : Point, y : Point)
(x - y).modulus
end
def average(xs : Array(Point))
xs.reduce { |x, y| x + y } / xs.size
end
def closest(x : Point, choices : Array(Point))
choices.min_by { |y| dist(x, y) }
end
def clusters(xs : Array(Point), centroids : Array(Point))
xs.group_by { |x| closest(x, centroids) }.values
end
def run(xs : Array(Point))
centroids = xs.first(N)
ITERS.times do
centroids = clusters(xs, centroids).map { |l| average(l) }
end
centroids
end
str = File.read("../points.json")
xs = Array(Point).new
Array(Array(Float64)).from_json(str) do |elem|
xs << Point.new elem.at(0), elem.at(1)
end
BM_ITERATIONS = 100
before = Time.now
BM_ITERATIONS.times do
centroids = run(xs)
# puts "centroids: \n #{centroids}"
end
after = Time.now
time = ((after - before) / BM_ITERATIONS).milliseconds
puts "Made #{BM_ITERATIONS} iterations with an average of #{time} milliseconds"
================================================
FILE: cuda/CMakeLists.txt
================================================
# CMakeLists.txt for G4CU project
project(kmeans)
# required cmake version
cmake_minimum_required(VERSION 2.8)
# packages
find_package(CUDA)
# nvcc flags
set(CUDA_SEPARABLE_COMPILATION ON)
cuda_add_executable(kmeans.out src/point.cu src/kmeans.cu src/main.cu)
target_link_libraries(kmeans.out jansson)
================================================
FILE: cuda/src/config.h
================================================
#ifndef CONFIGURATION_H_INCLUIDED
#define CONFIGURATION_H_INCLUIDED
// set to 1 if you want run repository specifications otherwise, 0
#define REPOSITORY_SPECIFICATION 1
// number of executions of the same algorithim
// its a specification of repository
#define TIMES 100
// its a repository specification.
// Its a number of iterations of each k-means execution
#define NUMBER_OF_ITERATIONS 15
// debug logs
#define DEBUG_LOGS 1
// number of centroids
extern int NUMBER_OF_CENTROIDS;
// number of points
extern int NUMBER_OF_POINTS;
#endif // CONFIGURATION_H_INCLUIDED
================================================
FILE: cuda/src/kmeans.cu
================================================
#include <stdio.h>
#include <stdlib.h>
#include "kmeans.h"
#include "point.h"
#include "config.h"
/**
Groups the points in a centroid.
*/
__global__ void km_group_by_cluster(Point* points, Centroid* centroids,
int num_centroids, int num_points)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
int i = 0;
float minor_distance = -1.0;
if (idx < num_points) {
for (i = 0; i < num_centroids; i++) {
float my_distance = km_distance(&points[idx], ¢roids[i]);
// if my_distance is less than the lower minor_distance
// or minor_distance is not yet started
if (minor_distance > my_distance || minor_distance == -1.0) {
minor_distance = my_distance;
points[idx].cluster = i;
}
}
}
}
/**
Sum the points of each centroid
*/
__global__ void km_sum_points_cluster(Point* points, Centroid* centroids,
int num_centroids, int num_points)
{
extern __shared__ Centroid s_centroids[];
int tdx = threadIdx.x;
int idx = blockIdx.x * blockDim.x + threadIdx.x;
// init global memory
if (idx < num_centroids) {
centroids[idx].x_sum = 0.0;
centroids[idx].y_sum = 0.0;
centroids[idx].num_points = 0.0;
}
// init shared memory
if (tdx < num_centroids) {
s_centroids[tdx].x_sum = 0.0;
s_centroids[tdx].y_sum = 0.0;
s_centroids[tdx].num_points = 0.0;
}
__syncthreads();
// use shared memory for intermediate sums
if (idx < num_points) {
int i = points[idx].cluster;
atomicAdd(&s_centroids[i].x_sum, points[idx].x);
atomicAdd(&s_centroids[i].y_sum, points[idx].y);
atomicAdd(&s_centroids[i].num_points, 1);
}
__syncthreads();
// then sum partial results in global memory, thus we reduce accesses to global memory
if (tdx < num_centroids) {
atomicAdd(¢roids[tdx].x_sum, s_centroids[tdx].x_sum);
atomicAdd(¢roids[tdx].y_sum, s_centroids[tdx].y_sum);
atomicAdd(¢roids[tdx].num_points, s_centroids[tdx].num_points);
}
}
/**
Update the centroids with current clustering.
Gets the x and y sum and divides by number of point for each centroid.\
*/
__global__ void km_update_centroids(Centroid* centroids, int num_centroids)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < num_centroids) {
if (centroids[idx].num_points > 0) {
centroids[idx].x = centroids[idx].x_sum / centroids[idx].num_points;
centroids[idx].y = centroids[idx].y_sum / centroids[idx].num_points;
}
}
}
/**
Compare the clusters of each point.
@param p1 - points of current iteration
@param p2 - points of last iteration
*/
__global__ void km_points_compare(Point* p1, Point* p2, int num_points,
int *result)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < num_points) {
// if any points has its cluster different, changes the result variable
if (p1[idx].cluster != p2[idx].cluster) {
*result = 0;
}
}
}
/**
Copy a point array.
Utilized to copy the status of points on the last iteration to compare them.
*/
__global__ void km_points_copy(Point* p_dest, Point* p_src, int num_points)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < num_points) {
p_dest[idx] = p_src[idx];
}
}
/**
* Executes the k-mean algorithm.
* To measure your global methods, use that:
*
* cudaEvent_t start, stop;
* float time;
* cudaEventCreate(&start);
* cudaEventCreate(&stop);
* cudaEventRecord(start, 0);
*
* // put your__global__ method here!
*
* cudaEventRecord(stop, 0);
* cudaEventSynchronize(stop);
* cudaEventElapsedTime(&time, start, stop);
* printf("%lf\n", times)
*/
void km_execute(Point* h_points, Centroid* h_centroids, int num_points,
int num_centroids)
{
int iterations = 0;
Point* d_points;
Point* d_points_old;
Centroid* d_centroids;
int h_res = 1;
int *d_res;
cudaMalloc((void**) &d_res, sizeof(int));
cudaMalloc((void**) &d_points_old, sizeof(Point) * num_points);
cudaMalloc((void **) &d_points, sizeof(Point) * num_points);
cudaMalloc((void **) &d_centroids, sizeof(Centroid) * num_centroids);
cudaMemcpy(d_points, h_points, sizeof(Point) * num_points, cudaMemcpyHostToDevice);
cudaMemcpy(d_centroids, h_centroids, sizeof(Centroid) * num_centroids, cudaMemcpyHostToDevice);
while (true) {
km_group_by_cluster<<<ceil(num_points/100), 100>>>(d_points, d_centroids,
num_centroids, num_points);
cudaDeviceSynchronize();
km_sum_points_cluster<<<ceil(num_points/100), 100, num_centroids*sizeof(Centroid)>>>(d_points, d_centroids,
num_centroids, num_points);
cudaDeviceSynchronize();
km_update_centroids<<<ceil(num_centroids/10), 10>>>(d_centroids, num_centroids);
cudaDeviceSynchronize();
if (REPOSITORY_SPECIFICATION == 1) {
// in repository specifications,
// we just want know if number of
// iterations is equals NUMBER_OF_ITERATIONS - 1 (iterations starts in 0)
if (iterations == (NUMBER_OF_ITERATIONS - 1)) {
break;
}
} else {
// TODO: WARNING:
// THIS IMPLEMENTATION IS NOT WORKING YET!
if (iterations > 0) {
h_res = 1;
cudaMemcpy(d_res, &h_res , sizeof(int), cudaMemcpyHostToDevice);
km_points_compare<<<ceil(num_points/10), 10>>>(d_points, d_points_old,
num_points, d_res);
cudaDeviceSynchronize();
cudaMemcpy(&h_res, d_res, sizeof(int), cudaMemcpyDeviceToHost);
// if h_rest == 1 the two vector of points are equal and the kmeans iterations
// has completed all work
if (h_res == 1) {
break;
}
}
km_points_copy<<<ceil(num_points/100), 100>>>(d_points_old, d_points,
num_points);
cudaDeviceSynchronize();
}
iterations++;
}
cudaMemcpy(h_centroids, d_centroids , sizeof(Centroid) * num_centroids, cudaMemcpyDeviceToHost);
cudaFree(d_points);
cudaFree(d_centroids);
cudaFree(d_points_old);
cudaFree(d_res);
}
================================================
FILE: cuda/src/kmeans.h
================================================
#ifndef KMEANS_H_INCLUDED
#define KMEANS_H_INCLUDED
#include "point.h"
__global__ void km_group_by_cluster(Point* points, Centroid* centroids,
int num_centroids);
__global__ void km_sum_points_cluter(Point* points, Centroid* centroids,
int num_centroids);
__global__ void km_update_centroids(Centroid* centroids);
__global__ void km_points_compare(Point* p1, Point* p2, int num_points,
int *result);
__global__ void km_points_copy(Point* p_dest, Point* p_src, int num_points);
void km_execute(Point* h_points, Centroid* h_centroids, int num_points,
int num_centroids);
void copy_points_to_kernel(Point* h_points, Point* d_points, int array_size);
void copy_centroids_to_kernel(Point* h_centroids, Point* d_centroids, int array_size);
#endif // KMEANS_H_INCLUDED
================================================
FILE: cuda/src/main.cu
================================================
#include <sys/types.h>
#include <math.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jansson.h>
#include <sys/time.h>
#include "point.h"
#include "kmeans.h"
#include "config.h"
int NUMBER_OF_POINTS = 100000;
int NUMBER_OF_CENTROIDS = 10;
void print_me(Centroid* centroids) {
if (!DEBUG_LOGS) {
return;
}
for (int i = 0; i < NUMBER_OF_CENTROIDS; i++) {
printf("[x=%lf, y=%lf, x_sum=%lf, y_sum=%lf, num_points=%i]\n",
centroids[i].x, centroids[i].y, centroids[i].x_sum,
centroids[i].y_sum, centroids[i].num_points);
}
printf("--------------------------------------------------\n");
}
long int run_kmeans_repo_specifications(Point* points, Centroid* centroids) {
struct timeval time_before, time_after, time_result;
gettimeofday(&time_before, NULL);
// load the initial centroids
for (int ci = 0; ci < NUMBER_OF_CENTROIDS; ci++) {
centroids[ci].x = points[ci].x;
centroids[ci].y = points[ci].y;
}
print_me(centroids);
for (int i = 0; i < TIMES; i++) {
km_execute(points, centroids, NUMBER_OF_POINTS, NUMBER_OF_CENTROIDS);
if (i + 1 == TIMES) {
print_me(centroids);
} else {
// load the centroids to next iteration
for (int ci = 0; ci < NUMBER_OF_CENTROIDS; ci++) {
centroids[ci].x = points[ci].x;
centroids[ci].y = points[ci].y;
}
}
}
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
long int ms = ((long int)time_result.tv_sec*1000) + ((long int)time_result.tv_usec/1000);
return ms / TIMES;
}
long int run_kmeans_rocks(Point* points, Centroid* centroids) {
// load the initial centroids
for (int i = 0; i < NUMBER_OF_CENTROIDS; i++) {
centroids[i].x = points[i].x;
centroids[i].y = points[i].y;
}
print_me(centroids);
struct timeval time_before, time_after, time_result;
gettimeofday(&time_before, NULL);
km_execute(points, centroids, NUMBER_OF_POINTS, NUMBER_OF_CENTROIDS);
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
long int ms = ((long int)time_result.tv_sec*1000) + ((long int)time_result.tv_usec/1000);
print_me(centroids);
return ms;
}
int main(int argc, char *argv[])
{
json_t *json;
json_error_t error;
size_t index;
long int total_time = 0;
json_t *value;
if (argc > 1 && argc < 4) {
printf("Usage: ./kmeans.out [input_file.json number_of_points number_of_centroids]\n");
return 0;
}
if (argc == 4) {
json = json_load_file(argv[1], 0, &error);
NUMBER_OF_POINTS = atoi(argv[2]);
NUMBER_OF_CENTROIDS = atoi(argv[3]);
}
else {
json = json_load_file("../points.json", 0, &error);
}
cudaSetDevice(0);
// 100.000 points it's the repository default.
Point* points = (Point*) malloc(NUMBER_OF_POINTS * sizeof(Point));
Centroid* centroids = (Centroid*) malloc(NUMBER_OF_CENTROIDS * sizeof(Centroid));
// validates json
if (!json) {
printf("Error parsing Json file");
fflush(stdout);
return -1;
}
// load points from json
json_array_foreach(json, index, value)
{
float x = json_number_value(json_array_get(value, 0));
float y = json_number_value(json_array_get(value, 1));
points[index].x = x;
points[index].y = y;
}
// call K-means
if (REPOSITORY_SPECIFICATION == 1) {
total_time = run_kmeans_repo_specifications(points, centroids);
} else {
total_time = run_kmeans_rocks(points, centroids);
}
free(centroids);
free(points);
printf("Average Time: %li ms\n", total_time);
cudaDeviceReset();
return 0;
}
================================================
FILE: cuda/src/point.cu
================================================
#include"point.h"
#include <stdlib.h>
#include <stdio.h>
__device__ void km_divide(Point* p, long d) {
p->x = p->x / ((float) d);
p->y = p->y / ((float) d);
return;
}
__device__ void km_add(Point* p1, Point* p2) {
p1->x = p1->x + p2->x;
p1->y = p1->y + p2->y;
return;
}
__device__ void km_sub(Point* p1, Point* p2) {
p1->x = p1->x - p2->x;
p1->y = p1->y - p2->y;
return;
}
__device__ float km_sq(float x) {
return x * x;
}
__device__ float km_modulus(Point* p) {
return sqrtf(km_sq(p->x) + km_sq(p->y));
}
__device__ float km_distance(Point* p, Centroid* c)
{
//printf("valor %lf\n", &c->x);
float dx = p->x - c->x;
float dy = p->y - c->y;
return sqrtf(dx*dx + dy*dy);
}
================================================
FILE: cuda/src/point.h
================================================
#ifndef POINT_H_INCLUDED
#define POINT_H_INCLUDED
typedef struct {
float x;
float y;
int cluster;
} Point;
typedef struct {
float x;
float y;
float x_sum;
float y_sum;
int num_points;
} Centroid;
__device__ void km_divide(Point* p, long d);
__device__ void km_add(Point* p1, Point* p2);
__device__ void km_sub(Point* p1, Point* p2);
__device__ float km_sq(float x);
__device__ float km_modulus(Point* p);
__device__ float km_distance(Point* p, Centroid* c);
#endif // POINT_H_INCLUDED
================================================
FILE: d/main.d
================================================
import std.stdio;
import std.math;
import std.json;
import std.file;
import std.datetime;
class Point
{
const double x;
const double y;
this(double x, double y)
{
this.x = x;
this.y = y;
}
Point add(Point p2)
{
return new Point(x+p2.x, y+p2.y);
}
Point sub(Point p2)
{
return new Point(x-p2.x, y-p2.y);
}
Point divide(double d)
{
return new Point(x/d, y/d);
}
double modulus()
{
return sqrt(sq(x) + sq(y));
}
}
auto sq = (double x) => x*x;
auto dist = (Point p1, Point p2) => p1.sub(p2).modulus();
Point average(Point[] points)
{
auto ret = new Point(0,0);
for (int i=0 ; i<points.length; i ++) {
ret = ret.add(points[i]);
}
return ret.divide(points.length);
}
Point closest(Point p, Point[] choices)
{
int min = 0;
double minDist = dist(p, choices[0]);
for (int i=0 ; i<choices.length; i ++) {
double actualDist = dist(p, choices[i]);
if (actualDist < minDist) {
min = i;
minDist = actualDist;
}
}
return choices[min];
}
Point[][] clusters(Point[] xs, Point[] centroids)
{
Point[][Point] hm;
for (int i=0;i<xs.length;i++) {
auto theClosest = closest(xs[i], centroids);
hm[theClosest] ~= [xs[i]];
}
return hm.values();
}
Point[][] run(int n, int iters, Point[] xs)
{
Point[] centroids = xs[0 .. n].dup();
for (int i=0;i<iters;i++) {
auto clus = clusters(xs, centroids);
for (int k=0;k<n;k++) {
centroids[k] = average(clus[k]);
}
}
return clusters(xs, centroids);
}
void main()
{
int n= 10;
int iters= 15;
int executions = 100;
Point xs[100000];
auto file = cast(char[])read("../points.json");
JSONValue json = parseJSON(file);
JSONValue[] values = json.array();
for (int i=0;i<values.length;i++) {
auto elem = values[i].array();
xs[i] = new Point(elem[0].floating,elem[1].floating);
}
auto before = Clock.currTime();
for (int i=0;i<executions;i++) {
run(n, iters, xs);
}
auto after = Clock.currTime();
auto totalTime = (after.stdTime() - before.stdTime())/10000/executions;
writeln("Average Time is: ", totalTime);
}
================================================
FILE: elixir/kmeans.ex
================================================
defmodule Kmeans do
defp sq(x) do
x * x
end
defp distance({x1, y1}, {x2, y2}) do
:math.sqrt( sq(x1 - x2) + sq(y1 - y2) )
end
defp closest(point, centroids) do
Enum.min_by centroids, &distance(&1, point)
end
defp clusters(centroids, points) do
Enum.group_by(points, &closest(&1, centroids)) |> Dict.values
end
defp sum({x1, y1}, {x2, y2}) do
{x1 + x2, y1 + y2}
end
defp shrink({x, y}, factor) do
{x / factor, y / factor}
end
defp average(cluster) do
List.foldl(tl(cluster), hd(cluster), &sum/2) |> shrink length(cluster)
end
defp step(points, iterations, centroids) do
case iterations do
0 -> centroids
_ -> step points, iterations - 1, Enum.map(clusters(centroids, points), &average/1)
end
end
def run(points, k, iterations) do
centroids = step points, iterations, Enum.take(points, k)
clusters centroids, points
end
end
================================================
FILE: elixir/main.exs
================================================
defmodule Main do
defp strip_brackets(xs) do
Enum.slice xs, 1, length(xs) - 2
end
defp parse_float(xs) do
Enum.map xs, fn(s) -> elem(Float.parse(s), 0) end
end
defp to_tuples(xs) do
case xs do
[] -> []
[a, b | tail] -> [{a, b} | to_tuples tail]
end
end
defp read_points(filename) do
File.read!(filename)
|> String.split(~r{[][,]+})
|> strip_brackets
|> parse_float
|> to_tuples
end
def main() do
times = 100
k = 10
iterations = 15
points = read_points "../points.json"
benchmarks = for _ <- 1..times do
{ elapsed, _ } = :timer.tc Kmeans, :run, [points, k, iterations]
elapsed / 1000
end
IO.puts "Made #{times} iterations with an average of #{Enum.sum(benchmarks) / times} ms"
end
end
Main.main()
================================================
FILE: erlang/kmeans.erl
================================================
-module(kmeans).
-export([run/3]).
-compile(inline).
run(Xs, N, Iters) ->
InitCentroids = lists:sublist(Xs, N),
Step = fun(_, Centroids) ->
[average(X) || X <- clusters(Xs, Centroids)]
end,
FinalCentroids = lists:foldl(Step, InitCentroids, lists:seq(1, Iters)),
clusters(Xs, FinalCentroids).
divide({Px,Py}, K) ->
{Px/K, Py/K}.
add({Px1, Py1}, {Px2, Py2}) ->
{(Px1+Px2), (Py1+Py2)}.
sub({Px1, Py1}, {Px2, Py2}) ->
{(Px1-Px2), (Py1-Py2)}.
sq(X) ->
X*X.
modulus({Px, Py}) ->
math:sqrt((sq(Px) + sq(Py))).
dist(P1, P2) ->
modulus(sub(P1,P2)).
average(Q) ->
divide(sum(Q),length(Q)).
sum(L) ->
Add = fun(X, Acc) -> add(X, Acc) end,
lists:foldl(Add, {0.0, 0.0}, L).
closest(P, Centroids) ->
element(2, lists:min([{dist(P, C), C} || C <- Centroids])).
clusters(Xs, Centroids) ->
groupBy(Xs, fun(X) -> closest(X, Centroids) end).
groupBy(L, Fn) ->
Group = fun(X, Dict) ->
Add = fun(T) -> [X|T] end,
dict:update(Fn(X), Add, [X], Dict)
end,
Dict = lists:foldl(Group, dict:new(), L),
[ V || {_,V} <- dict:to_list(Dict)].
================================================
FILE: erlang/main.erl
================================================
-module(main).
-export([run/0]).
times() -> 100.
n() -> 10.
iters() -> 15.
run() ->
Xs = read_points("../points.json"),
Times = [getTime(Xs) || _ <- lists:seq(1, times())],
Time = lists:sum(Times)/times(),
Time.
read_points(FileName) ->
{ok, Data} = file:read_file(FileName),
[<<>>|Bins] = re:split(Data, "[][,]+", [trim]),
points([binary_to_float(X) || X <- Bins]).
getTime(Xs) ->
Ms = element(1, timer:tc(kmeans, run, [Xs, n(), iters()]))/1000,
% io:write(Ms), io:nl(),
Ms.
points([]) -> [];
points([H1, H2 | T]) ->
[{H1, H2} | points(T)].
================================================
FILE: factor/kmeans/benchmark/benchmark.factor
================================================
USING: generalizations io.encodings.utf8 io.files json.reader kernel kmeans tools.time ;
IN: kmeans.benchmark
: load-points ( path -- points ) utf8 file-contents json> ;
: kmeans-benchmark ( runs path -- )
load-points [
[ dup 15 swap 10 kmeans drop ] repeat
] time drop ;
================================================
FILE: factor/kmeans/kmeans.factor
================================================
USING: assocs generalizations kernel math.statistics math.vectors sequences ;
IN: kmeans
: closest ( ys x -- y ) [ distance ] curry infimum-by ;
: clusters ( xs centroids -- clusters ) [ swap closest ] curry collect-by values ;
: vsum ( vs -- w ) { 0 0 } [ v+ ] reduce ;
: avg ( vs -- w ) [ vsum ] [ length ] bi v/n ;
: centroids ( clusters -- centroids ) [ avg ] map ;
: kmeans-start ( xs n -- clusters ) dupd head clusters ;
: kmeans-step ( clusters -- clusters ) [ concat ] [ centroids ] bi clusters ;
: kmeans ( iters xs n -- clusters ) kmeans-start [ kmeans-step ] repeat ;
================================================
FILE: fsharp/.gitignore
================================================
*.exe
paket.lock
.paket/paket.exe
packages
*.dll
!.paket/paket.bootstrapper.exe
================================================
FILE: fsharp/Makefile
================================================
default: all
all:
mono .paket/paket.bootstrapper.exe
mono .paket/paket.exe install
cp packages/Newtonsoft.Json/lib/net40/Newtonsoft.Json.dll ./
fsharpc --standalone -r:packages/Newtonsoft.Json/lib/net40/Newtonsoft.Json.dll kmeans.fs main.fs
run:
mono main.exe
================================================
FILE: fsharp/kmeans.fs
================================================
module Kmeans
type Point = { x: double; y: double }
let sq (x: double) = x*x
type Point with
static member (+) (p1: Point, p2: Point) =
{ x = p1.x + p2.x; y = p1.y + p2.y }
static member (-) (p1: Point, p2: Point) =
{ x = p1.x - p2.x; y = p1.y - p2.y }
static member (*) (p1: Point, p2: Point) =
{ x = p1.x * p2.x; y = p1.y * p2.y }
static member (/) (p: Point, d: double) =
{ x = p.x / d; y = p.y / d }
static member Zero = { x = 0.0; y = 0.0 }
member this.modulus = sqrt ( sq(this.x) + sq(this.y))
let dist (p1: Point, p2: Point) = (p1 - p2).modulus
let average (xs: Point list) = (xs |> List.sum) / (xs.Length |> double)
let closest (p: Point, xs: Point list) =
xs |> List.minBy( fun x -> dist (p, x) )
let clusters (xs: Point list, centroids: Point list) =
xs |> List.groupBy( fun x -> closest ( x, centroids)) |> List.map snd
let rec run (xs: Point list, centroids: Point list, iters: int) =
match iters with
| 1 ->
let finalCentroids = clusters ( xs, centroids) |> List.map average
//printfn "Final centroids are %A" finalCentroids
finalCentroids
| _ -> run (xs, clusters ( xs, centroids) |> List.map average, iters - 1)
let start (xs: Point list, iters: int, n: int) =
run (xs, xs |> List.take n, iters)
================================================
FILE: fsharp/main.fs
================================================
open Kmeans
open System.IO
open FSharp.Data
open Newtonsoft.Json
open Newtonsoft.Json.Linq
let file = File.ReadAllText(@"../points.json")
let json = JArray.Parse(file)
let getPoint (e: JToken) =
{ x = (double (e.Item(0).ToString())); y = (double (e.Item(1).ToString())) }
let xs = [ for i in 0 .. (json.Count-1) -> getPoint(json.Item(i)) ]
let iterations = 100
let stopWatch = System.Diagnostics.Stopwatch.StartNew()
for i in 1 .. iterations do
start (xs, 15, 10) |> ignore
stopWatch.Stop()
let time = stopWatch.Elapsed.TotalMilliseconds / (float iterations)
printfn "Average time is %f" time
================================================
FILE: fsharp/paket.dependencies
================================================
source https://nuget.org/api/v2
nuget Newtonsoft.Json
================================================
FILE: go/.gitignore
================================================
main
================================================
FILE: go/main.go
================================================
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"math"
"time"
)
func sq(x float64) float64 {
return x * x
}
type Point struct {
x, y float64
}
func (p Point) add(p2 Point) Point {
return Point{p.x + p2.x, p.y + p2.y}
}
func (p Point) sub(p2 Point) Point {
return Point{p.x - p2.x, p.y - p2.y}
}
func (p Point) divide(d float64) Point {
return Point{p.x / d, p.y / d}
}
func (p Point) modulus() float64 {
return math.Sqrt(sq(p.x) + sq(p.y))
}
func dist(p1 Point, p2 Point) float64 {
return (p1.sub(p2)).modulus()
}
func average(points []Point) Point {
tmp := Point{0, 0}
for _, point := range points {
tmp = tmp.add(point)
}
tmp = tmp.divide(float64(len(points)))
return tmp
}
func closest(p Point, choices []Point) int {
min := 0
minDist := math.MaxFloat64
for i, choice := range choices {
actualDist := dist(p, choice)
if minDist > actualDist {
min = i
minDist = actualDist
}
}
return min
}
func clusters(xs []Point, centroids []Point) [][]Point {
hm := make([][]Point, len(centroids))
for _, x := range xs {
theClosest := closest(x, centroids)
hm[theClosest] = append(hm[theClosest], x)
}
i := 0
for i < len(hm) {
if len(hm[i]) > 0 {
i++
} else {
hm = append(hm[:i], hm[i+1:]...)
}
}
return hm
}
func run(n int, iters int, xs []Point) [][]Point {
centroids := make([]Point, n)
copy(centroids, xs)
for k := 0; k < iters; k++ {
clus := clusters(xs, centroids)
for i := 0; i < n; i++ {
centroids[i] = average(clus[i])
}
}
/*
fmt.Println("Final Centroids are ")
for _, centroid := range centroids {
fmt.Println(centroid)
}*/
return clusters(xs, centroids)
}
func main() {
executions := 100
iters := 15
n := 10
dat, err := ioutil.ReadFile("../points.json")
if err != nil {
fmt.Println("Error reading file ")
panic(err)
}
res := &[][]float64{}
json.Unmarshal(dat, &res)
xs := []Point{}
for _, res := range *res {
xs = append(xs, Point{res[0], res[1]})
}
before := time.Now()
for ex := 0; ex < executions; ex++ {
run(n, iters, xs)
}
after := time.Now()
time := (after.Sub(before).Nanoseconds()) / int64(1000000) / int64(executions)
fmt.Println("Average time is ", time)
}
================================================
FILE: haskell/Kmeans.hs
================================================
module Kmeans where
import Data.List (minimumBy)
import Data.Ord (comparing)
import Data.Map (Map, fromListWith, elems)
import Debug.Trace (trace)
import Point
closest :: Point -> [Point] -> Point
closest p qs = minimumBy (comparing (dist p)) qs
groupBy :: Ord b => (a -> b) -> [a] -> Map b [a]
groupBy f xs = fromListWith (++) [(f x, [x]) | x <- xs]
clusters :: [Point] -> [Point] -> [[Point]]
clusters ps centroids = elems $ groupBy (flip closest centroids) ps
run :: [Point] -> Int -> Int -> [[Point]]
run ps iters n = step ps centroids iters
where
centroids = take n ps
step ps centroids iters =
let newClusters = clusters ps centroids in
if iters == 0 then newClusters -- trace (show centroids) newClusters
else step ps (map average newClusters) (iters - 1)
================================================
FILE: haskell/Main.hs
================================================
module Main where
import Text.JSON (decode, Result(..))
import Text.Printf (printf)
import System.CPUTime (getCPUTime)
import Control.DeepSeq (deepseq)
import Point (Point(..))
import Kmeans (run)
readPoints :: String -> [Point]
readPoints string = map readPoint xs
where
xs = case (decode string :: Result [[Double]]) of
Ok t -> t
_ -> error "Invalid JSON"
readPoint [x, y] = Point x y
main = do
content <- readFile "../points.json"
let ps = readPoints content
start <- ps `deepseq` getCPUTime -- in picoseconds, deepseq forces evaluation
let clusters = run ps 15 10 -- how to run 100 times?
end <- clusters `deepseq` getCPUTime
let diff = (fromIntegral (end - start)) / (10^9)
printf "Made 1 iteration in %0.1f ms\n" (diff :: Double)
================================================
FILE: haskell/Point.hs
================================================
module Point where
import GHC.Float (int2Double)
import Control.DeepSeq (NFData)
data Point = Point Double Double deriving (Show, Eq)
(+.) :: Point -> Point -> Point
(Point x1 y1) +. (Point x2 y2) = Point (x1 + x2) (y1 + y2)
(-.) :: Point -> Point -> Point
(Point x1 y1) -. (Point x2 y2) = Point (x1 - x2) (y1 - y2)
(/.) :: Point -> Double -> Point
(Point x y) /. k = Point (x / k) (y / k)
norm :: Point -> Double
norm (Point x y) = sqrt $ (x * x) + (y * y)
dist :: Point -> Point -> Double
dist p q = norm $ p -. q
psum :: [Point] -> Point
psum = foldl (+.) (Point 0 0)
average :: [Point] -> Point
average ps = (psum ps) /. int2Double (length ps)
instance Ord Point where
(Point x1 y1) `compare` (Point x2 y2) =
let c = x1 `compare` x2 in
if c == EQ then y1 `compare` y2 else c
instance NFData Point -- needed to force evaluation
================================================
FILE: haskell/Setup.hs
================================================
import Distribution.Simple
main = defaultMain
================================================
FILE: haskell/kmeans.cabal
================================================
-- Initial kmeans.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
name: kmeans
version: 0.1.0.0
-- synopsis:
-- description: kmeans
-- license:
license-file: LICENSE
author: Andrea Ferretti
maintainer: ferrettiandrea@gmail.com
-- copyright:
-- category:
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
executable kmeans
main-is: Main.hs
-- other-modules:
-- other-extensions:
build-depends: base >=4.6, containers >= 0.5, json >= 0.3, deepseq >= 1.3
-- hs-source-dirs:
default-language: Haskell2010
================================================
FILE: java/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>unicredit</groupId>
<artifactId>kmeans-java</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>Entry</mainClass>
<arguments></arguments>
</configuration>
</plugin>
</plugins>
</build>
</project>
================================================
FILE: java/src/main/java/Entry.java
================================================
import java.io.File;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
public class Entry {
static int times = 100;
public static void main(String[] args) throws Exception {
JsonFactory factory = new JsonFactory();
JsonParser jp = factory.createJsonParser(new File("../points.json"));
Point[] Xs = new Point[100000];
int i = 0;
while (true) {
JsonToken actual = jp.nextValue();
while (actual == JsonToken.START_ARRAY) {
actual = jp.nextValue();
}
try {
double x = jp.getDoubleValue();
jp.nextToken();
double y = jp.getDoubleValue();
Xs[i] = new Point(x,y);
i++;
} catch(Exception ex) {
//ex.printStackTrace();
break;
}
actual = jp.nextToken();
while (jp.nextToken() == JsonToken.END_ARRAY) {
actual = jp.nextToken();
}
}
jp.close();
KMeans kmeans = new KMeans(Xs);
long totalTime = 0;
long timeBefore = System.currentTimeMillis();
for (int k=0;k<times;k++) {
kmeans.run();
}
long timeAfter = System.currentTimeMillis();
totalTime = timeAfter -timeBefore;
System.out.println("Average time "+(totalTime/times));
}
private static void executionTime(KMeans kmeans) {
kmeans.run();
return;
}
}
================================================
FILE: java/src/main/java/KMeans.java
================================================
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
public class KMeans {
private int n = 10;
private int iters = 15;
private Point[] Xs;
private Point[] Centroids;
public KMeans(Point[] Xs, int n, int iters) {
this.Xs = Xs;
this.n = n;
this.iters = iters;
}
public KMeans(Point[] Xs) {
this.Xs = Xs;
}
private double dist(Point p1, Point p2) {
return p1.sub(p2).modulus();
}
private Point average(ArrayList<Point> xs) {
double size = xs.size();
Iterator<Point> iter = xs.iterator();
Point p = new Point(0,0);
while (iter.hasNext()) {
p.addToThis(iter.next());
}
p.divideToThis(size);
return p;
}
private Point closest(Point x, Point[] choices) {
double minVal = dist(x, choices[0]);
int min = 0;
for (int i=1;i<choices.length;i++) {
double actualDist = dist(x, choices[i]);
if (actualDist < minVal) {
min = i;
minVal = actualDist;
}
}
return choices[min];
}
private Collection<ArrayList<Point>> clusters() {
HashMap<Point, ArrayList<Point>> hm = new HashMap<Point, ArrayList<Point>>();
for (int i=0;i<Xs.length; i++) {
Point Key = closest(Xs[i], Centroids);
ArrayList<Point> alp = hm.get(Key);
if (alp == null)
alp = new ArrayList<Point>();
alp.add(Xs[i]);
hm.put(Key, alp);
}
return hm.values();
}
public Collection<ArrayList<Point>> run() {
Centroids = new Point[n];
for(int i=0;i<n;i++)
Centroids[i] = Xs[i];
for(int i=0;i<iters;i++) {
Collection<ArrayList<Point>> clusters = clusters();
int k = 0;
for (ArrayList<Point> cluster: clusters) {
Centroids[k] = average(cluster);
k++;
}
}
return clusters();
}
}
================================================
FILE: java/src/main/java/Point.java
================================================
public class Point {
double x = 0;
double y = 0;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public Point divide(double d) {
return new Point(x/d,y/d);
}
public void divideToThis(double d) {
x = x/d;
y = y/d;
return;
}
public Point add(Point p2) {
return new Point(x + p2.x, y + p2.y);
}
public void addToThis(Point p2) {
x = x + p2.x;
y = y + p2.y;
return;
}
public Point sub(Point p2) {
return new Point(x - p2.x, y - p2.y);
}
private double sq(double x) {
return x*x;
}
public double modulus() {
return Math.sqrt(sq(x) + sq(y));
}
@Override public String toString() {
return "(" + x + "," + y + ")";
}
}
================================================
FILE: java8/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.demos</groupId>
<artifactId>java8-kmeans</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
<version>2.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>com.example.Main</mainClass>
<arguments></arguments>
</configuration>
</plugin>
</plugins>
</build>
</project>
================================================
FILE: java8/src/main/java/com/example/KMeans.java
================================================
package com.example;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.stream.Collectors.*;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.minBy;
/**
* Created by evacchi on 27/02/15.
*/
public class KMeans {
int n = 10;
int iters = 15;
public void run(List<Point> xs) {
Stream<Point> centroids = xs.stream().limit(n);
for (int i = 0; i < iters; i++) {
centroids = clusters(xs, centroids.collect(toList()))
.stream().map(this::average);
}
List<Point> ps = centroids.collect(toList());
clusters(xs, ps);
}
public Collection<List<Point>> clusters(List<Point> xs, List<Point> centroids) {
return xs.stream().collect(groupingBy((Point x) -> closest(x, centroids))).values();
}
public Point closest(final Point x, List<Point> choices) {
return choices.stream()
.collect(minBy((y1, y2) -> dist(x, y1) <= dist(x, y2) ? -1 : 1)).get();
}
public double sq(double x) { return x*x; }
public double dist(Point x, Point y) { return x.minus(y).getModulus(); }
public Point average(List<Point> xs) {
return xs.stream().reduce(Point::plus).get().div(xs.size());
}
}
================================================
FILE: java8/src/main/java/com/example/Main.java
================================================
package com.example;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.text.MessageFormat;
import java.util.List;
import static java.util.stream.Collectors.toList;
/**
* Created by evacchi on 28/02/15.
*/
public class Main {
private List<Point> readPoints(String path) throws Exception {
JsonParser json = new JsonFactory().createParser(new File(path));
ObjectMapper mapper = new ObjectMapper();
TypeReference<List<List<Double>>> typeReference = new TypeReference<List<List<Double>>>(){};
return mapper.<List<List<Double>>>readValue(json, typeReference).stream().map( x -> new Point(x.get(0), x.get(1)) ).collect(toList());
}
public void main() throws Exception {
final int iterations = 100;
final List<Point> points = readPoints("../points.json");
final KMeans kMeans = new KMeans();
long start = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
kMeans.run(points);
}
long time = (System.currentTimeMillis() - start) / iterations;
System.out.println(MessageFormat.format("Made {0} iterations with an average of" +
" {1} milliseconds", iterations, time));
}
public static void main(String[] args) throws Exception {
new Main().main();
}
}
================================================
FILE: java8/src/main/java/com/example/Point.java
================================================
package com.example;
/**
* Created by evacchi on 28/02/15.
*/
class Point {
double x,y;
public Point(double x, double y) {
this.x = x; this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public Point plus(Point p2) {
return new Point(x + p2.getX(), y + p2.getY());
}
public Point minus(Point p2) {
return new Point(x - p2.getX(), y - p2.getY());
}
public Point div(double d) {
return new Point(x/d, y/d);
}
public Double getModulus() { return Math.sqrt(sq(x) + sq(y)); }
private double sq(double x) { return x*x; }
@Override
public String toString() {
return "(" +x+", "+y+")";
}
}
================================================
FILE: julia/kmeans.jl
================================================
# do Pkg.add("JSON") first
import Base.+
import Base./
using JSON
type Point
x::Float64
y::Float64
end
+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y)
/(p::Point, k::Number) = Point(p.x / k, p.y / k)
dist(p1::Point, p2::Point) = sqrt((p1.x - p2.x)^2 + (p1.y - p2.y)^2)
function closest(p1::Point, points)
mindist = Inf
min_i = 0
for i in 1:length(points)
disti = dist(p1, points[i])
if disti < mindist
mindist = disti
min_i = i
end
end
return points[min_i]
end
function groupby(points, centroids)
g = Dict{Point, Vector{Point}}()
for p in points
c = closest(p, centroids)
if haskey(g, c)
push!(g[c], p)
else
g[c] = [p]
end
end
return g
end
update_centroids(points, centroids) = [mean(g) for g in values(groupby(points, centroids))]
function run(xs, n, iters=15)
centroids = xs[1:n]
for i in 1:iters
centroids = update_centroids(xs, centroids)
end
return groupby(xs, centroids)
end
function main()
points = [Point(x[1], x[2]) for x in JSON.parsefile("../points.json")]
iterations = 100
tic()
for i in 1:iterations
run(points, 10)
end
avgtime = toq() * 1000 / iterations
println("Made $iterations iterations with an average of $avgtime milliseconds")
end
main()
================================================
FILE: kotlin/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kmeans</groupId>
<artifactId>kotlin-kmeans</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.1-M01</kotlin.version>
</properties>
<repositories>
<repository>
<id>sonatype.oss.snapshots</id>
<name>Sonatype OSS Snapshot Repository</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>bintray-kotlin-kotlin-eap-1.1</id>
<name>bintray</name>
<url>http://dl.bintray.com/kotlin/kotlin-eap-1.1</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>sonatype.oss.snapshots</id>
<name>Sonatype OSS Snapshot Repository</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>bintray-kotlin-kotlin-eap-1.1</id>
<name>bintray-plugins</name>
<url>http://dl.bintray.com/kotlin/kotlin-eap-1.1</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
<version>2.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals> <goal>test-compile</goal> </goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>KmeansKt</mainClass>
<arguments></arguments>
</configuration>
</plugin>
</plugins>
</build>
</project>
================================================
FILE: kotlin/src/main/java/kmeans.kt
================================================
import java.io.File
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper
//--------------------------------------------------------------------
//-- Constants -------------------------------------------------------
//--------------------------------------------------------------------
val N = 10
val times = 15
val iterations = 100
//--------------------------------------------------------------------
//-- Tools -----------------------------------------------------------
//--------------------------------------------------------------------
fun <T> millisToRun(thunk: () -> T): Pair<T,Long>
{
val start = System.currentTimeMillis()
val result = thunk()
val time = System.currentTimeMillis() - start
return Pair(result, time)
}
// specialized (and faster) version of 'minBy'
fun <V, T: Collection<V>> T.minBy(selector: (pt: V) -> Double): V
{
var minE = this.first()
var minV = Double.MAX_VALUE
for (e in this) {
val v = selector(e)
if (v < minV) {
minV = v
minE = e
}
}
return minE
}
//--------------------------------------------------------------------
//-- Point -----------------------------------------------------------
//--------------------------------------------------------------------
data class Point(val x: Double, val y: Double)
{
operator fun plus(pt: Point) =
Point(this.x + pt.x, this.y + pt.y)
operator fun div(d: Double) =
Point(this.x / d, this.y / d)
fun distanceTo(pt: Point): Double
{
val x = this.x - pt.x
val y = this.y - pt.y
return Math.sqrt((x * x) + (y * y))
}
}
//--------------------------------------------------------------------
//-- Points ----------------------------------------------------------
//--------------------------------------------------------------------
typealias Points = List<Point>
fun Points.closestTo(pt: Point) =
this.minBy(pt::distanceTo)
fun Points.average(): Point =
this.reduce(Point::plus) / this.size.toDouble()
//--------------------------------------------------------------------
//-- Main ------------------------------------------------------------
//--------------------------------------------------------------------
fun readPoints(path: String): Points
{
val mapper = ObjectMapper()
val typeref = object : TypeReference<List<List<Double>>>() {}
val list = mapper.readValue<List<List<Double>>>(File(path), typeref)
return list.map { Point(it[0], it[1]) }
}
fun run(points: Points): Points =
(1 .. times).fold( points.take(N) ) { centroids, ix ->
points.groupBy(centroids::closestTo)
.values
.map(Points::average)
}
fun main(args: Array<String>)
{
val points = readPoints("../points.json")
val (centroids, time) = millisToRun {
(2 .. iterations).forEach { run(points) }
run(points)
}
print("ran $iterations iterations, ")
println("average of ${time / iterations} milliseconds.")
centroids.forEach(::println)
}
//--------------------------------------------------------------------
================================================
FILE: lisp/kmeans.lisp
================================================
(declaim (optimize (speed 3) (space 0) (debug 0) (safety 0) (compilation-speed 0)))
(defconstant n 10)
(defconstant iterations 15)
(defconstant executions 100)
(defstruct (point (:constructor make-point (x y)))
(x 0.0D0 :type double-float)
(y 0.0D0 :type double-float))
(declaim (inline add addf
divide dividef
modulus dist
average averagef
closest clusters))
(defun add (p1 p2)
(declare (point p1 p2))
(make-point (+ (point-x p1) (point-x p2))
(+ (point-y p1) (point-y p2))))
(defun addf (p1 p2)
(declare (point p1 p2))
(setf (point-x p1) (+ (point-x p1) (point-x p2))
(point-y p1) (+ (point-y p1) (point-y p2)))
p1)
(defun divide (p d &aux (df (coerce d 'double-float)))
(declare (point p))
(make-point (/ (point-x p) df)
(/ (point-y p) df)))
(defun dividef (p d &aux (df (coerce d 'double-float)))
(declare (point p))
(setf (point-x p) (/ (point-x p) df)
(point-y p) (/ (point-y p) df))
p)
(defun modulus (x y)
(declare (double-float x y))
(sqrt (the (double-float 0.0D0) (+ (* x x) (* y y)))))
(defun dist (p1 p2)
(declare (point p1 p2))
(modulus (- (point-x p1) (point-x p2))
(- (point-y p1) (point-y p2))))
(defun average (points)
(loop :with sum := (make-point 0.0D0 0.0D0)
:for point :in points
:for length :of-type fixnum :from 1
:do (addf sum point)
:finally (return (dividef sum length))))
(defun averagef (average points)
(declare (point average))
(setf (point-x average) 0.0D0
(point-y average) 0.0D0)
(loop :for point :in points
:for length :of-type fixnum :from 1
:do (addf average point)
:finally (return (dividef average length))))
(defun closest (rp choices)
(loop :with min := (first choices)
:with min-dist :of-type double-float := (dist rp min)
:for point :in (rest choices)
:for dist :of-type double-float := (dist rp point)
:when (< dist min-dist)
:do (setq min-dist dist min point)
:finally (return min)))
(defun clusters (xs centroids)
(loop :with clusters := (make-hash-table :test 'eq)
:for x :in xs
:do (push x (gethash (closest x centroids) clusters))
:finally (return clusters)))
(defun main-loop (xs)
(loop :repeat executions
:for centroids := (loop :repeat n
:for point :in xs
:collect (copy-point point))
:do (loop :repeat iterations
:for clusters := (clusters xs centroids)
:do (loop :for centroid :in centroids
:do (averagef centroid (gethash centroid clusters))))
:finally (return centroids)))
(defun make-points-readtable ()
(let ((readtable (with-standard-io-syntax (copy-readtable))))
(set-macro-character #\[ (lambda (stream char)
(declare (ignore char))
(loop :for char := (read-char stream t nil t)
:until (char= char #\])
:do (unread-char char stream)
:collect (read stream t nil t)))
nil readtable)
(set-syntax-from-char #\] #\) readtable)
(set-syntax-from-char #\, #\ readtable)
readtable))
(defun benchmark ()
(let* ((xs (mapcar (lambda (p) (apply 'make-point p))
(let ((*readtable* (make-points-readtable))
(*read-default-float-format* 'double-float))
(with-open-file (in "../points.json" :direction :input) (read in)))))
(start (get-internal-real-time))
(centroids (main-loop xs))
(stop (get-internal-real-time)))
(format t "Last centroids are: ~{~%~A~}~%" centroids)
(format t "Elapsed time is ~A~%" (/ (/ (* (- stop start) internal-time-units-per-second) 1000.0) executions))))
(benchmark)
================================================
FILE: lisp/readme.txt
================================================
This is fairly straightforward, portable Common Lisp code. No additional libraries are necessary.
The code has been tested on several Common Lisp implementations, but for benchmarking this particular
code, SBCL is recommended. There is a shell script that shows how to invoke SBCL to run this code.
If SBCL is not available in your package manager, you can download a binary from http://sbcl.org/platform-table.html
================================================
FILE: lua/kmeans.lua
================================================
local sqrt = math.sqrt
local clock = os.clock
local json = require("dkjson")
local Point = {}
Point.__index = Point
setmetatable(Point, {
__call = function(self, x, y)
return setmetatable({_x=x, _y=y}, Point)
end
})
function Point:x()
return self._x
end
function Point:y()
return self._y
end
function Point:__add(other)
return Point(self._x + other._x, self._y + other._y)
end
function Point:__div(value)
return Point(self._x / value, self._y / value)
end
function Point:dist(other)
return sqrt((self._x - other._x)^2 + (self._y - other._y)^2)
end
function Point:closest(points)
local min = math.huge
local min_i
for i, point in ipairs(points) do
local dist = self:dist(point)
if dist < min then
min = dist
min_i = i
end
end
return points[min_i]
end
function Point:__tostring()
return ("Point(%f,%f)"):format(self._x, self._y)
end
local function sum(t, start)
local total = start or 0
for _, i in ipairs(t) do
total = total + i
end
return total
end
local function len(t)
local l = 0
for _ in pairs(t) do
l = l + 1
end
return l
end
local function groupby(points, centroids)
local g = {}
for _, p in ipairs(points) do
local c = p:closest(centroids)
g[c] = g[c] or {}
table.insert(g[c], p)
end
return g
end
local function update_centroids(points, centroids)
local groups = groupby(points, centroids)
local res = {}
local i = 1
for _, g in pairs(groups) do
res[i] = sum(g, Point(0, 0)) / len(g)
i = i + 1
end
return res
end
local function run(xs, n, iters)
iters = iters or 15
local centroids = {}
for i = 1, n do
table.insert(centroids, xs[i])
end
for i = 1, iters do
centroids = update_centroids(xs, centroids)
end
return groupby(xs, centroids)
end
if not ... then
local data = json.decode(io.open("../points.json"):read("*a"))
local points = {}
for i, x in ipairs(data) do
points[i] = Point(x[1], x[2])
end
local start = clock()
local iterations = 100
for i = 1, iterations do
run(points, 10)
end
local total = (clock() - start) * 1000 / iterations
print(("Made %d iterations with an average of %.2f milliseconds"):format(iterations, total))
end
================================================
FILE: nim/algo.nim
================================================
import math, hashes, tables, sequtils
type
Point* = tuple[x, y: float]
Points* = seq[Point]
Centroids = openarray[Point]
proc hash(p: Point): THash {.noInit.} =
!$(p.x.hash !& p.y.hash)
proc `+`(p, q: Point): Point {.noInit.} =
(p.x + q.x, p.y + q.y)
proc `-`(p, q: Point): Point {.noInit.} =
(p.x - q.x, p.y - q.y)
proc `/`(p: Point, k: float): Point {.noInit.} =
(p.x / k, p.y / k)
proc norm(p: Point): float {.noInit.} =
sqrt(p.x * p.x + p.y * p.y)
proc dist(p, q: Point): float {.noInit.} =
norm(p - q)
proc closest(p: Point, centroids: Centroids): Point {.noInit.} =
var minDist = Inf
for centroid in centroids:
let d = dist(p, centroid)
if d < minDist:
minDist = d
result = centroid
proc groupBy(points: Points, centroids: Centroids): Table[Point,Points] =
result = initTable[Point, Points]()
for c in centroids:
result[c] = @[]
for point in points:
let centroid = point.closest(centroids)
result.mget(centroid).add(point)
proc average(points: Points): Point =
foldl(points, a + b) / float(points.len)
proc updateCentroids(points: Points, centroids: var Centroids) =
let groups = points.groupBy(centroids)
var ix = 0
for group in groups.values:
centroids[ix] = average(group)
ix += 1
proc calculateCentroids*(points: Points, centroids: var Centroids,
iterations: int = 15) =
for ix, x in centroids:
centroids[ix] = points[ix]
for i in 1 .. iterations:
updateCentroids(points, centroids)
================================================
FILE: nim/benchmark.nim
================================================
import times, json, math, strutils, algo
const
n = 10
iterations = 100
filename = "../points.json"
proc loadPoints(): Points =
result = newSeq[Point]()
for p in parseFile(filename).items:
result.add((x: p[0].fnum, y: p[1].fnum))
proc main() =
let points = loadPoints()
var centroids : array[n, Point]
let start = cpuTime()
for i in 1 .. iterations:
calculateCentroids(points, centroids)
let time = (((cpuTime() - start) * 1000) / float(iterations)).round
echo format("Made $1 iterations with an average of $2 miliseconds",
iterations, time)
for centroid in centroids:
echo centroid
when isMainModule:
main()
================================================
FILE: node/kmeans.js
================================================
var _ = require("lodash");
var fs = require("fs");
function sq(x) { return x * x }
function dist(x, y) {
return Math.sqrt(sq(x[0] - y[0]) + sq(x[1] - y[1]));
}
function closest(x, choices) {
return _.min(choices, function(y) { return dist(x, y); });
}
function clusters(xs, centroids) {
return _(xs)
.groupBy(function (x) { return closest(x, centroids); })
.values()
.value();
}
function vsum(v, w) {
return _.map(v, function(x, i) { return x + w[i]; });
}
function average(xs) {
var total = _.reduce(xs, vsum);
var l = xs.length;
return _.map(total, function(t) { return t / l; });
}
function run(xs, n, iters) {
var centroids = _.take(xs, n);
for (var i = 0; i < iters; i++) {
centroids = _.map(clusters(xs, centroids), average);
}
return clusters(xs, centroids);
}
var points = JSON.parse(fs.readFileSync("../points.json"));
var iterations = 100;
var n = 10;
var start = (new Date()).getTime();
for (var i = 0; i < iterations; i++) {
run(points, n, 15);
}
var time = ((new Date()).getTime() - start) / iterations;
console.log("Running " + iterations + " iterations as required " + time + " ms");
================================================
FILE: node/package.json
================================================
{
"name": "kmeans",
"dependencies": {
"lodash": "*"
}
}
================================================
FILE: ocaml/kmeans.ml
================================================
open Core.Std
open Point
let min_by f xs =
let Some h = List.hd xs in
let m = f h in
let (_, min_elt) = List.fold xs ~init:(m, h)
~f:(fun (a, x) y -> let b = f y in (if b < a then (b, y) else (a, x))) in
min_elt
let closest p qs = min_by (dist p) qs
let sum qs = List.fold qs ~init:{x = 0.0; y = 0.0} ~f:( ++ )
let average qs = (sum qs) // (qs |> List.length |> Float.of_int)
let group_by xs f =
let table = Hashtbl.Poly.create () in
List.iter xs (fun x ->
let y = f x in
match Hashtbl.find table y with
| Some l -> Hashtbl.replace table ~key:y ~data:(x :: l)
| None -> Hashtbl.replace table ~key:y ~data:[x]);
table
let clusters xs centroids =
group_by xs (fun p -> closest p centroids)
|> Hashtbl.data
let run points iters n =
let centroids = ref (List.take points n) in
let new_clusters = ref (clusters points !centroids) in
for i = 1 to iters do
centroids := List.map !new_clusters average;
new_clusters := clusters points !centroids;
done;
!new_clusters
================================================
FILE: ocaml/kmeans.mli
================================================
open Core.Std
val run: Point.t list -> int -> int -> Point.t list list
================================================
FILE: ocaml/main.ml
================================================
open Core.Std
let read_point json =
let open Yojson.Basic.Util in
let open Point in
let [x; y] = List.map (json |> to_list) ~f:to_float in
{ x; y }
let read_points path =
let json = Yojson.Basic.from_file path in
let open Yojson.Basic.Util in
let values = json |> to_list in
List.map values ~f:read_point
let () =
let runs = 100 in
let points = read_points "../points.json" in
let start = Time.now() in
for i = 1 to runs do
ignore(Kmeans.run points 15 10);
done;
let finish = Time.now() in
let milliseconds = (Time.diff finish start) |> Time.Span.to_ms in
Printf.printf "We made 100 iterations with an average of %f ms\n" (milliseconds /. (Float.of_int runs))
================================================
FILE: ocaml/point.ml
================================================
open Core.Std
type t = { x: float; y: float }
let ( ++ ) { x = x1; y = y1 } { x = x2; y = y2 } = { x = x1 +. x2; y = y1 +. y2 }
let ( -- ) { x = x1; y = y1 } { x = x2; y = y2 } = { x = x1 -. x2; y = y1 -. y2 }
let ( // ) { x; y } k = { x = x /. k; y = y /. k }
let norm { x; y } = sqrt (x *. x +. y *. y)
let dist x y = norm (x -- y)
================================================
FILE: opencl/.gitignore
================================================
kmeans
================================================
FILE: opencl/kmeans.cl
================================================
#include "point.h"
float dist(__global Point* p, __global Centroid* c)
{
float dx = p->x - c->x;
float dy = p->y - c->y;
return dx*dx + dy*dy;
}
__kernel void group_by_cluster(__global Point* points, __global Centroid* centroids, int num_points, int num_centroids) {
int idx = get_global_id(0);
int i = 0;
float min_distance = -1.0;
if (idx < num_points) {
for (i = 0; i < num_centroids; i++) {
float d = dist(points + idx, centroids + i);
if (min_distance > d || min_distance == -1.0) {
min_distance = d;
points[idx].cluster = i;
}
}
}
}
__kernel void sum_points(__global Point* points, __global Accum* accum, __local Accum* scratch, int num_points, int num_centroids) {
int lid = get_local_id(0);
int gid = get_global_id(0);
int wid = get_group_id(0);
int pos = lid * num_centroids;
int s;
int j;
for (s = pos; s < pos + num_centroids; s++) {
scratch[s].x_sum = 0.0;
scratch[s].y_sum = 0.0;
scratch[s].num_points = 0;
}
if (gid < num_points) {
int cluster = points[gid].cluster;
scratch[pos + cluster].x_sum = points[gid].x;
scratch[pos + cluster].y_sum = points[gid].y;
scratch[pos + cluster].num_points = 1;
}
barrier(CLK_LOCAL_MEM_FENCE);
for(s = get_local_size(0) / 2; s > 0; s = s / 2) {
if (lid < s) {
for (j = 0; j < num_centroids; j++) {
int dst = pos + j;
int src = pos + j + s * num_centroids;
scratch[dst].x_sum += scratch[src].x_sum;
scratch[dst].y_sum += scratch[src].y_sum;
scratch[dst].num_points += scratch[src].num_points;
}
}
barrier(CLK_LOCAL_MEM_FENCE);
}
if (lid == 0) {
for (j = 0; j < num_centroids; j++) {
int h = wid * num_centroids + j;
accum[h].x_sum = scratch[pos + j].x_sum;
accum[h].y_sum = scratch[pos + j].y_sum;
accum[h].num_points = scratch[pos + j].num_points;
}
}
}
__kernel void update_centroids(__global Accum* accum, __global Centroid* centroids, int work_groups, int num_centroids) {
int gid = get_global_id(0);
float x_sum = 0.0;
float y_sum = 0.0;
int num_points = 0;
int j;
if (gid < num_centroids) {
for (j = 0; j < work_groups; j++) {
int h = j * num_centroids + gid;
x_sum += accum[h].x_sum;
y_sum += accum[h].y_sum;
num_points += accum[h].num_points;
}
if (num_points > 0) {
centroids[gid].x = x_sum / num_points;
centroids[gid].y = y_sum / num_points;
}
}
}
================================================
FILE: opencl/kmeans.nim
================================================
import times, json, os, math, strutils, opencl, util, point
proc loadPoints(filename: string): seq[Point] =
result = newSeq[Point]()
for p in parseFile(filename).items:
result.add(Point(x: p[0].fnum, y: p[1].fnum, cluster: -1))
proc main() =
const
body = staticRead("kmeans.cl")
n = 10
iterations = 100
var
points = loadPoints("../points.json")
centroids = newSeq[Centroid](n)
let
platform = getPlatformByName("NVIDIA CUDA")
devices = platform.getDevices
context = devices.createContext
program = context.createProgram(body)
queue = context.commandQueueFor(devices[0])
workGroups = devices[0].maxWorkGroups
workItems = (points.len div workGroups).nextPowerOfTwo
program.buildOn(devices)
let
groupByCluster = program.createKernel("group_by_cluster")
sumPoints = program.createKernel("sum_points")
updateCentroids = program.createKernel("update_centroids")
start = cpuTime()
gpuPoints = context.buffer(points)
gpuCentroids = context.buffer(centroids)
gpuAccum = buffer[Accum](context, centroids.len * workGroups)
groupByCluster.args(gpuPoints, gpuCentroids, points.len.int32, centroids.len.int32)
sumPoints.args(gpuPoints, gpuAccum, LocalBuffer[Accum](centroids.len * workItems), points.len.int32, centroids.len.int32)
updateCentroids.args(gpuAccum, gpuCentroids, workGroups.int32, centroids.len.int32)
for _ in 1 .. iterations:
for i in 0 .. < centroids.len:
centroids[i].x = points[i].x
centroids[i].y = points[i].y
queue.write(points, gpuPoints)
queue.write(centroids, gpuCentroids)
for _ in 1 .. 15:
queue.run(groupByCluster, points.len)
queue.run(sumPoints, workItems * workGroups, workItems)
queue.run(updateCentroids, centroids.len)
queue.read(centroids, gpuCentroids)
let time = (((cpuTime() - start) * 1000) / float(iterations)).round
echo format("Made $1 iterations with an average of $2 milliseconds",
iterations, time)
for a in centroids:
echo a
# Clean up
release(queue)
release(groupByCluster)
release(sumPoints)
release(updateCentroids)
release(program)
release(gpuPoints)
release(gpuCentroids)
release(context)
when isMainModule:
main()
================================================
FILE: opencl/kmeans.nimble
================================================
mode = ScriptMode.Verbose
packageName = "kmeans-opencl"
version = "0.1.0"
author = "Andrea Ferretti"
description = "OpenCL experiment"
license = "Apache2"
requires "nim >= 0.13.0", "opencl >= 1.0"
template dependsOn*(task: untyped): stmt =
exec "nimble " & astToStr(task)
task headers, "compile headers with c2nim":
exec "c2nim point.h"
task kmeans, "run kmeans example":
dependsOn headers
switch("cincludes", "/usr/local/cuda/targets/x86_64-linux/include")
switch("clibdir", "/usr/local/cuda/targets/x86_64-linux/lib")
--define: release
--path: "."
--run
setCommand "c", "kmeans"
================================================
FILE: opencl/point.h
================================================
typedef struct {
float x;
float y;
int cluster;
} Point;
typedef struct {
float x;
float y;
} Centroid;
typedef struct {
float x_sum;
float y_sum;
int num_points;
} Accum;
================================================
FILE: opencl/point.nim
================================================
type
Point* = object
x*: cfloat
y*: cfloat
cluster*: cint
Centroid* = object
x*: cfloat
y*: cfloat
Accum* = object
x_sum*: cfloat
y_sum*: cfloat
num_points*: cint
================================================
FILE: opencl/util.nim
================================================
import opencl
type
PlatformNotFound = object of Exception
DeviceNotFound = object of Exception
proc newPlatformNotFound(): ref PlatformNotFound =
new result
result.msg = "PlatformNotFound"
proc newDeviceNotFound(): ref DeviceNotFound =
new result
result.msg = "DeviceNotFound"
proc name*(id: PPlatformId): string =
var size = 0
check getPlatformInfo(id, PLATFORM_NAME, 0, nil, addr size)
result = newString(size)
check getPlatformInfo(id, PLATFORM_NAME, size, addr result[0], nil)
proc name*(id: PDeviceId): string =
var size = 0
check getDeviceInfo(id, DEVICE_NAME, 0, nil, addr size)
result = newString(size)
check getDeviceInfo(id, DEVICE_NAME, size, addr result[0], nil)
proc maxWorkGroups*(id: PDeviceId): int =
check getDeviceInfo(id, DEVICE_MAX_WORK_GROUP_SIZE, sizeof(int), addr result, nil)
proc localMemory*(id: PDeviceId): uint64 =
check getDeviceInfo(id, DEVICE_LOCAL_MEM_SIZE, sizeof(int), addr result, nil)
proc globalMemory*(id: PDeviceId): uint64 =
check getDeviceInfo(id, DEVICE_GLOBAL_MEM_SIZE, sizeof(int), addr result, nil)
proc maxWorkItems*(id: PDeviceId): seq[int] =
var dims: int
check getDeviceInfo(id, DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(int), addr dims, nil)
result = newSeq[int](dims)
check getDeviceInfo(id, DEVICE_MAX_WORK_ITEM_SIZES, dims * sizeof(int), addr result[0], nil)
proc version*(id: PPlatformId): string =
var size = 0
check getPlatformInfo(id, PLATFORM_VERSION, 0, nil, addr size)
result = newString(size)
check getPlatformInfo(id, PLATFORM_VERSION, size, addr result[0], nil)
proc getPlatformByName*(platformName: string): PPlatformId =
var numPlatforms: uint32
check getPlatformIDs(0, nil, addr numPlatforms)
var platforms = newSeq[PPlatformId](numPlatforms)
check getPlatformIDs(numPlatforms, addr platforms[0], nil)
for platform in platforms:
if platform.name.substr(0, platformName.high) == platformName:
return platform
raise newPlatformNotFound()
proc getDevices*(platform: PPlatformId): seq[PDeviceId] =
var numDevices: uint32
check getDeviceIDs(platform, DEVICE_TYPE_ALL, 0, nil, addr numDevices)
if numDevices == 0:
raise newDeviceNotFound()
var devices = newSeq[PDeviceId](numDevices)
check getDeviceIDs(platform, DEVICE_TYPE_ALL, numDevices, addr devices[0], nil)
devices
proc createContext*(devices: seq[PDeviceId]): PContext =
var status: TClResult
var devs = devices
result = createContext(nil, devs.len.uint32, cast[ptr PDeviceId](addr devs[0]), nil, nil, addr status)
check status
proc createProgram*(context: PContext, body: string): PProgram =
var status: TClResult
var lines = [cstring(body)]
result = createProgramWithSource(context, 1, cast[cstringArray](addr lines), nil, addr status)
check status
proc buffer*[A](context: PContext, size: int, flags: Tmem_flags = MEM_READ_WRITE): PMem =
var status: TClResult
result = createBuffer(context, flags, size * sizeof(A), nil, addr status)
check status
proc buffer*[A](context: PContext, xs: seq[A], flags: Tmem_flags = MEM_READ_WRITE): PMem =
buffer[A](context, xs.len, flags)
proc buildOn*(program: PProgram, devices: seq[PDeviceId]) =
var devs = devices
check buildProgram(program, devs.len.uint32, cast[ptr PDeviceId](addr devs[0]), nil, nil, nil)
proc buildErrors*(program: PProgram, devices: seq[PDeviceId]): string =
var logSize: int
check getProgramBuildInfo(program, devices[0], PROGRAM_BUILD_LOG, 0, nil, addr logSize)
result = newString(logSize + 1)
check getProgramBuildInfo(program, devices[0], PROGRAM_BUILD_LOG, logSize, addr result[0], nil)
proc commandQueueFor*(context: PContext, device: PDeviceId): PCommandQueue =
var status: TClResult
result = createCommandQueue(context, device, 0, addr status)
check status
proc createKernel*(program: PProgram, name: string): PKernel =
var status: TClResult
result = createKernel(program, name, addr status)
check status
type
LocalBuffer*[A] = distinct int
anyInt = int or int32 or int64
template setArg(kernel: PKernel, item: PMem, index: int) =
var x = item
check setKernelArg(kernel, index.uint32, sizeof(Pmem), addr x)
template setArg[A](kernel: PKernel, item: var A, index: int) =
check setKernelArg(kernel, index.uint32, sizeof(A), addr item)
template setArg[A](kernel: PKernel, item: LocalBuffer[A], index: int) =
check setKernelArg(kernel, index.uint32, int(item) * sizeof(A), nil)
template setArg(kernel: PKernel, item: anyInt, index: int) =
var x = item
check setKernelArg(kernel, index.uint32, sizeof(type(item)), addr x)
proc args*[A1](kernel: PKernel, a1: A1) =
kernel.setArg(a1, 0)
proc args*[A1, A2](kernel: PKernel, a1: A1, a2: A2) =
kernel.setArg(a1, 0)
kernel.setArg(a2, 1)
proc args*[A1, A2, A3](kernel: PKernel, a1: A1, a2: A2, a3: A3) =
kernel.setArg(a1, 0)
kernel.setArg(a2, 1)
kernel.setArg(a3, 2)
proc args*[A1, A2, A3, A4](kernel: PKernel, a1: A1, a2: A2, a3: A3, a4: A4) =
kernel.setArg(a1, 0)
kernel.setArg(a2, 1)
kernel.setArg(a3, 2)
kernel.setArg(a4, 3)
proc args*[A1, A2, A3, A4, A5](kernel: PKernel, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5) =
kernel.setArg(a1, 0)
kernel.setArg(a2, 1)
kernel.setArg(a3, 2)
kernel.setArg(a4, 3)
kernel.setArg(a5, 4)
proc args*[A1, A2, A3, A4, A5, A6](kernel: PKernel, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6) =
kernel.setArg(a1, 0)
kernel.setArg(a2, 1)
kernel.setArg(a3, 2)
kernel.setArg(a4, 3)
kernel.setArg(a5, 4)
kernel.setArg(a6, 5)
proc run*(queue: PCommandQueue, kernel: PKernel, totalWork: int) =
var globalWorkSize = [totalWork, 0, 0]
check enqueueNDRangeKernel(queue, kernel, 1, nil, cast[ptr int](addr globalWorkSize), nil, 0, nil, nil)
proc run*(queue: PCommandQueue, kernel: PKernel, totalWork, localWork: int) =
var
globalWorkSize = [totalWork, 0, 0]
localWorkSize = [localWork, 0, 0]
check enqueueNDRangeKernel(queue, kernel, 1, nil, cast[ptr int](addr globalWorkSize), cast[ptr int](addr localWorkSize), 0, nil, nil)
proc write*(queue: PCommandQueue, src: pointer, dest: PMem, size: int) =
check enqueueWriteBuffer(queue, dest, CL_FALSE, 0, size, src, 0, nil, nil)
proc write*[A](queue: PCommandQueue, src: var seq[A], dest: PMem) =
write(queue, addr src[0], dest, src.len * sizeof(A))
proc read*(queue: PCommandQueue, dest: pointer, src: PMem, size: int) =
check enqueueReadBuffer(queue, src, CL_TRUE, 0, size, dest, 0, nil, nil)
proc read*[A](queue: PCommandQueue, dest: var seq[A], src: PMem) =
read(queue, addr dest[0], src, dest.len * sizeof(A))
template release*(queue: PCommandQueue) = check releaseCommandQueue(queue)
template release*(kernel: PKernel) = check releaseKernel(kernel)
template release*(program: PProgram) = check releaseProgram(program)
template release*(buffer: PMem) = check releaseMemObject(buffer)
template release*(context: PContext) = check releaseContext(context)
================================================
FILE: openmp/compile.sh
================================================
gcc -Wall -O3 -c hashmap.c -o hashmap.o `pkg-config --cflags --libs glib-2.0`
gcc -Wall -O3 -c kmeans.c -o kmeans.o
gcc -Wall -O3 -c main.c -o main.o
gcc -Wall -O3 -c point.c -o point.o
g++ -o kmeans hashmap.o kmeans.o main.o point.o `pkg-config --cflags --libs glib-2.0` -s -ljansson
================================================
FILE: openmp/makefile
================================================
#
# build the openmp project.
#
# usage:
# normal build:
# $make
#
# clean project:
# $make clean
#
# @author tmaltempi@gmail.com
# @since 18/06/2015
#
all: make-all
GCC=gcc
GPP=g++
make-all: clean kmeans.o main.o point.o kmeans
kmeans.o: src/kmeans.c
$(GCC) -Wall -O3 -c ./src/kmeans.c -o ./build/kmeans.o -fopenmp
main.o: src/main.c
gcc -Wall -O3 -c ./src/main.c -o ./build/main.o -fopenmp
point.o: src/point.c
$(GCC) -Wall -O3 -c ./src/point.c -o ./build/point.o -fopenmp
kmeans:
$(GPP) -o kmeans.out ./build/kmeans.o ./build/main.o ./build/point.o -s -ljansson -fopenmp
clean:
#create a backup of actual kmeans.out if exists
/bin/sh -c 'if [ ! -d "build" ]; then mkdir build; fi'
/bin/sh -c 'if [ -f kmeans.out ]; then mv kmeans.out kmeans.out.lastupdated; fi'
rm -rf ./build/*
================================================
FILE: openmp/src/config.h
================================================
#ifndef CONFIGURATION_H_INCLUIDED
#define CONFIGURATION_H_INCLUIDED
// set to 1 if you want run repository specifications otherwise, 0
#define REPOSITORY_SPECIFICATION 0
// number of executions of the same algorithim
// its a specification of repository
#define TIMES 100
// its a repository specification.
// Its a number of iterations of each k-means execution
#define NUMBER_OF_ITERATIONS 15
// debug logs
#define DEBUG_LOGS 1
// Number of threads
extern int NUM_THREAD;
// number of centroids
extern int NUMBER_OF_CENTROIDS;
// number of points
extern int NUMBER_OF_POINTS;
#endif // CONFIGURATION_H_INCLUIDED
================================================
FILE: openmp/src/kmeans.c
================================================
#include <stdio.h>
#include <stdlib.h>
#include "kmeans.h"
#include "point.h"
#include <omp.h>
#include "config.h"
void group_by_cluster(Point* points, Centroid* centroids)
{
int i, j;
# pragma omp parallel for num_threads(NUM_THREAD) \
default(none) firstprivate(centroids, points, NUMBER_OF_CENTROIDS, NUMBER_OF_POINTS) private(i, j)
for (i = 0; i < NUMBER_OF_POINTS; i++) {
double minor_distance = -1.0;
for (j = 0; j < NUMBER_OF_CENTROIDS; j++) {
double my_distance = km_distance(&points[i], ¢roids[j]);
// if my_distance is less than the lower minor_distance
// or minor_distance is not yet started
if (minor_distance > my_distance || minor_distance == -1.0) {
minor_distance = my_distance;
points[i].centroid = j;
}
}
}
}
void sum_points_cluster(Point* points, Centroid* centroids)
{
int i, j;
for (i =0 ; i < NUMBER_OF_POINTS; i++) {
for (j = 0; j < NUMBER_OF_CENTROIDS; j++) {
if (points[i].centroid == j) {
centroids[j].x_sum = centroids[j].x_sum + points[i].x;
centroids[j].y_sum = centroids[j].y_sum + points[i].y;
centroids[j].num_points = centroids[j].num_points + 1;
}
}
}
}
void update_centroids(Centroid* centroids)
{
int i;
for (i = 0; i < NUMBER_OF_CENTROIDS; i++) {
if (centroids[i].num_points > 0) {
centroids[i].x = centroids[i].x_sum / centroids[i].num_points;
centroids[i].y = centroids[i].y_sum / centroids[i].num_points;
}
}
}
void clear_last_iteration(Centroid* centroids)
{
int i;
for (i = 0; i < NUMBER_OF_CENTROIDS; i++) {
// clear the last iteration sums
centroids[i].x_sum = 0.0;
centroids[i].y_sum = 0.0;
centroids[i].num_points = 0.0;
}
}
/**
* Executes the k-mean algorithm.
*/
void km_execute(Point* points, Centroid* centroids)
{
int i = 0;
for (i = 0; i < NUMBER_OF_ITERATIONS; i++) {
clear_last_iteration(centroids);
group_by_cluster(points, centroids);
sum_points_cluster(points, centroids);
update_centroids(centroids);
}
}
================================================
FILE: openmp/src/kmeans.h
================================================
#ifndef KMEANS_H_INCLUDED
#define KMEANS_H_INCLUDED
#include "point.h"
void km_execute(Point* h_points, Centroid* h_centroids);
#endif // KMEANS_H_INCLUDED
================================================
FILE: openmp/src/main.c
================================================
#include <stdio.h>
#include <stdlib.h>
#include "point.h"
#include <string.h>
#include <jansson.h>
#include <sys/time.h>
#include <omp.h>
#include "kmeans.h"
#include "config.h"
int NUMBER_OF_POINTS = 100000;
int NUMBER_OF_CENTROIDS = 10;
int NUM_THREAD = 4;
void print_me(Centroid* centroids)
{
if (DEBUG_LOGS == 0) {
return;
}
int i;
for (i = 0; i < NUMBER_OF_CENTROIDS; i++) {
printf("[x=%lf, y=%lf, x_sum=%lf, y_sum=%lf, num_points=%i]\n",
centroids[i].x, centroids[i].y, centroids[i].x_sum,
centroids[i].y_sum, centroids[i].num_points);
}
printf("--------------------------------------------------\n");
}
long int run_kmeans(Point* points, Centroid* centroids)
{
struct timeval time_before, time_after, time_result;
gettimeofday(&time_before, NULL);
int ci, i;
// # pragma omp parallel for num_threads(NUMBER_OF_THREADS) default(none) private(ci) firstprivate(points, centroids, NUMBER_OF_CENTROIDS)
// load the initial centroids
for (ci = 0; ci < NUMBER_OF_CENTROIDS; ci++) {
centroids[ci].x = points[ci].x;
centroids[ci].y = points[ci].y;
centroids[ci].x_sum = 0;
centroids[ci].y_sum = 0;
centroids[ci].num_points = 0;
}
print_me(centroids);
for (i = 0; i < TIMES; i++) {
km_execute(points, centroids);
if (i + 1 == TIMES) {
print_me(centroids);
} else {
// load the centroids to next iteration
for (ci = 0; ci < NUMBER_OF_CENTROIDS; ci++) {
centroids[ci].x = points[ci].x;
centroids[ci].y = points[ci].y;
}
}
}
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
long int ms = ((long int) time_result.tv_sec * 1000)
+ ((long int) time_result.tv_usec / 1000);
return ms / TIMES;
}
int main(int argc, char *argv[])
{
json_t *json;
json_error_t error;
size_t index;
long int total_time = 0;
json_t *value;
if (argc > 1 && argc < 5) {
printf("Usage: ./kmeans.out [input_file.json number_of_points number_of_centroids number_of_threads]\n");
printf("or... ./kmeans.out [number_of_threads] \n");
return 0;
}
if (argc == 2) {
NUM_THREAD = atoi(argv[1]);
json = json_load_file("../points.json", 0, &error);
}
else if (argc == 5) {
json = json_load_file(argv[1], 0, &error);
NUMBER_OF_POINTS = atoi(argv[2]);
NUMBER_OF_CENTROIDS = atoi(argv[3]);
NUM_THREAD = atoi(argv[4]);
}
else {
json = json_load_file("../points.json", 0, &error);
}
// printf("NUM_THREAD: %i | NUM_OF_POINTS: %i | NUM_OF_CENTROIDS: %i | FILENAME %s\n", NUM_THREAD, NUMBER_OF_POINTS, NUMBER_OF_CENTROIDS, argv[1]);
Point* points = (Point*) malloc(NUMBER_OF_POINTS * sizeof(Point));
Centroid* centroids = (Centroid*) malloc(
NUMBER_OF_CENTROIDS * sizeof(Centroid));
// validates json
if (!json) {
printf("Error parsing Json file");
fflush(stdout);
return -1;
}
// load points from json
json_array_foreach(json, index, value)
{
float x = json_number_value(json_array_get(value, 0));
float y = json_number_value(json_array_get(value, 1));
points[index].x = x;
points[index].y = y;
points[index].centroid = 0;
}
// call K-means
total_time = run_kmeans(points, centroids);
free(centroids);
free(points);
printf("Average Time: %li ms\n", total_time);
return 0;
}
================================================
FILE: openmp/src/point.c
================================================
#include <math.h>
#include "point.h"
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
void divide(Point* p, long d)
{
p->x = p->x/((double)d);
p->y = p->y/((double)d);
return;
}
void add(Point* p1, Point* p2)
{
p1->x = p1->x+p2->x;
p1->y = p1->y+p2->y;
return;
}
void sub(Point* p1, Point* p2)
{
p1->x = p1->x-p2->x;
p1->y = p1->y-p2->y;
return;
}
double sq(double x)
{
return x*x;
}
double modulus(Point* p)
{
return sqrt(sq(p->x)+ sq(p->y));
}
double km_distance(Point* p, Centroid* c)
{
double dx = p->x - c->x;
double dy = p->y - c->y;
return sqrt(dx*dx + dy*dy);
}
================================================
FILE: openmp/src/point.h
================================================
#ifndef POINT_H_INCLUDED
#define POINT_H_INCLUDED
typedef struct {
double x;
double y;
int centroid;
} Point;
typedef struct {
double x;
double y;
double x_sum;
double y_sum;
int num_points;
} Centroid;
void divide(Point* p, long d);
void add(Point* p1, Point* p2);
void sub(Point* p1, Point* p2);
double sq(double x);
double modulus(Point* p);
double km_distance(Point* p, Centroid* c);
#endif // POINT_H_INCLUDED
================================================
FILE: parasail/benchmark.psl
================================================
func main (Args: Basic_Array <Univ_String>) is
var R := Random::Start(11)
var S := Random::Start(12)
var Points: Vector<Point> := []
for I := 0 then I + 1 while I < 500 loop
Points |= Point::New(Next_Real(R), Next_Real(S))
end loop
var C := Clock::Create()
const Start := C.Now()
KMeans::Run(Points, 10, 15)
const Elapsed_Time := C.Now() - Start
Println("It took " | Elapsed_Time | " seconds")
end func main
================================================
FILE: parasail/kmeans.psl
================================================
interface KMeans<> is
func Run(PS: Vector<Point>; N: Univ_Integer; Iters: Univ_Integer) -> Vector<Vector<Point>>
end interface KMeans
class KMeans is
func Average(PS: Vector<Point>) -> Point is
const L := Length(PS) * 1.0
var Q := Point::New(0.0, 0.0)
for each P of PS loop
Q += P
end loop
return Q / L
end func Average
func Values(Groups: Map<Point, Vector<Point>>) -> Result: Vector<Vector<Point>> is
Result := []
for each [K => V] of Groups loop
Result |= V
end loop
end func Values
func Clusters(PS: Vector<Point>; Centroids: Vector<Point>) -> Vector<Vector<Point>> is
var Groups: Map<Point, Vector<Point>> := []
for each P of PS loop
const Q := Closest(P, Centroids)
if Q in Groups then
Groups[Q] |= P
else
Groups[Q] := [P]
end if
end loop
return Values(Groups)
end func Clusters
func Closest(P: Point; QS: Vector<Point>) { QS.magnitude > 0 } -> Point is
var X: optional Point := null
var m: optional Univ_Real := null
for each Q of QS loop
const d := Dist(P, Q)
if m is null or else d < m then
m := d
X := Q
end if
end loop
return X
end func Closest
func Take(PS: Vector<Point>; N: Univ_Integer) -> Result: Vector<Point> is
Result := []
for I := 1 then I + 1 while I <= N loop
Result |= PS[I]
end loop
end func Take
exports
func Run(PS: Vector<Point>; N: Univ_Integer; Iters: Univ_Integer) -> Vector<Vector<Point>> is
var Centroids := Take(PS, N)
for I := 0 then I + 1 while I < Iters loop
const Groups := Clusters(PS, Centroids)
Centroids := []
for each G of Groups loop
Centroids |= Average(G)
end loop
end loop
return Clusters(PS, Centroids)
end func Run
end class KMeans
================================================
FILE: parasail/point.psl
================================================
interface Point<> is
func New(X: Univ_Real; Y: Univ_Real) -> Point
func To_String(P: Point) -> Univ_String
func Println(P: Point) is (Println(To_String(P)))
op "=?"(P, Q: Point) -> Ordering // is (To_String(P) =? To_String(Q))
func Hash(P: Point) -> Univ_Integer // is (Hash(To_String(P)))
func Dist(P, Q: Point) -> Univ_Real
op "+" (P, Q: Point) -> Point
op "+=" (var P: Point; Q: Point)
op "-" (P, Q: Point) -> Point
op "/" (P: Point; K: Univ_Real) { K != 0.0 } -> Point
end interface Point
class Point is
var X: Univ_Real
var Y: Univ_Real
func Norm(P: Point) -> Univ_Real is
return Sqrt(P.X * P.X + P.Y * P.Y)
end func Norm
exports
func New(X: Univ_Real; Y: Univ_Real) -> Point is
return (X => X, Y => Y)
end func New
func To_String(P: Point) -> Univ_String is
return "(" | P.X | ", " | P.Y | ")"
end func To_String
func Hash(P: Point) -> Univ_Integer is
return 104543 * Hash(P.X) + Hash(P.Y)
end func Hash
op "=?" (P, Q : Point) -> Ordering is
if P.X != Q.X then
return P.X =? Q.X
else
return P.Y =? Q.Y
end if
end op "=?"
op "+" (P, Q: Point) -> Point is
return New(P.X + Q.X, P.Y + Q.Y)
end op "+"
op "+=" (var P: Point; Q: Point) is
P.X += Q.X
P.Y += Q.Y
end op "+="
op "-" (P, Q: Point) -> Point is
return New(P.X - Q.X, P.Y - Q.Y)
end op "-"
op "/" (P: Point; K: Univ_Real) { K != 0.0 } -> Point is
return New(P.X / K, P.Y / K)
end op "/"
func Dist(P, Q: Point) -> Univ_Real is
return Norm(P - Q)
end func Dist
end class Point
================================================
FILE: perl/kmeans.pl
================================================
#!/usr/bin/env perl
use warnings;
use strict;
use 5.20.0;
use JSON;
use List::Util qw(reduce);
open my $POINTS, '<', '../points.json' or die $!;
my $json = from_json(join('', <$POINTS>));
my @points = map { [$_->[0], $_->[1]] } @{$json};
my $iterations = 100;
my $start = time;
for my $i (0 .. $iterations - 1) {
run(\@points, 10);
}
my $total = (time - $start) * 1000 / $iterations;
say "Made $iterations iterations with an average of $total milliseconds";
sub run {
my ($xs, $n, $iters) = @_;
$iters //= 15;
my $centroids = [@{$xs}[0 .. $n-1]];
for my $i (0 .. $iters - 1) {
$centroids = update_centroids($xs, $centroids);
}
return groupby($xs, $centroids);
}
sub update_centroids {
my ($points, $centroids) = @_;
my $groups = groupby($points, $centroids);
my @res = ();
for my $g (values %{$groups}) {
my $len = scalar @{$g};
my $psum = reduce { [$a->[0] + $b->[0], $a->[1] + $b->[1]] } [0,0], @{$g};
$psum->[0] /= $len;
$psum->[1] /= $len;
push @res, $psum;
}
return \@res;
}
sub groupby {
my ($points, $centroids) = @_;
my %g = ();
for my $p (@{$points}) {
my $c = closest($p, $centroids);
push @{$g{$c}}, $p;
}
return \%g;
}
sub dist {
return sqrt(($_[0]->[0] - $_[1]->[0])**2 + ($_[0]->[1] - $_[1]->[1])**2);
}
sub closest {
my $point = shift;
my $min = 9999999999999999;
my $min_centroid = [];
for my $c (@{$_[0]}) {
my $dist = dist($point, $c);
if ($dist < $min) {
$min = $dist;
$min_centroid = $c;
}
}
return $min_centroid;
}
================================================
FILE: pharo3/KMeans.st
================================================
Object subclass: #KMeans
instanceVariableNames: 'iterations clusters'
classVariableNames: ''
poolDictionaries: ''
category: 'KMeans'!
!KMeans commentStamp: 'RoelWuyts 3/31/2016 09:37' prior: 0!
I implement an idiomatic version of the kmeans algorithm in order to compare to implementations in other languages - see https://github.com/andreaferretti/kmeans .
To use me:
- download Pharo and launch an image.
- put the points.json in the same directory than the image.
- type "KMeans benchmark: 100" (in the Playground or anywhere else),
- select the text and 'Print it' in the contextual menu.
- wait...!
!KMeans methodsFor: 'algorithm' stamp: 'AndreaFerretti 10/8/2014 18:57'!
run: points
| centroids |
centroids := points first: clusters.
iterations timesRepeat: [
centroids := (self cluster: points around: centroids) collect: [ :each | each average ]
].
^ self cluster: points around: centroids! !
!KMeans methodsFor: 'algorithm' stamp: 'RoelWuyts 3/1/2016 09:51'!
cluster: points around: centroids
^ (points groupedBy: [ :p | p closestFrom: centroids ]) values! !
!KMeans methodsFor: 'algorithm' stamp: 'AndreaFerretti 10/8/2014 19:01'!
run: points times: times
times timesRepeat: [ self run: points ].! !
!KMeans methodsFor: 'benchmarks' stamp: 'AndreaFerretti 10/8/2014 19:03'!
benchmark: points repeating: repetitions
| time |
time := Time millisecondsToRun: [ self run: points times: repetitions ].
^ time / repetitions.! !
!KMeans methodsFor: 'initialization' stamp: 'RoelWuyts 2/29/2016 17:07'!
clusters: numClusters iterations: numIterations
iterations := numIterations.
clusters := numClusters! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
KMeans class
instanceVariableNames: ''!
!KMeans class methodsFor: 'benchmarks' stamp: 'RoelWuyts 3/31/2016 09:24'!
benchmark: repetitions pointsFilename: pointsFilename
"self benchmark: 100 pointsFilename: 'points.json' "
| fileref str points |
fileref := pointsFilename asFileReference.
str := FileStream readOnlyFileNamed: fileref.
points := (MCFileTreeJsonParser parseStream: str) collect: [:arr | Point x: arr first y: arr second ].
^(self clusters: 10 iterations: 15)
benchmark: points repeating: repetitions! !
!KMeans class methodsFor: 'benchmarks' stamp: 'RoelWuyts 3/31/2016 09:25'!
benchmark: repetitions
"self benchmark: 100"
^self benchmark: repetitions pointsFilename: self pointsFilename ! !
!KMeans class methodsFor: 'benchmarks' stamp: 'RoelWuyts 3/31/2016 09:23'!
pointsFilename
"The name and location of the file that contains the points used for the benchmarking."
"By default it is assumed to be next to your Pharo image."
^'points.json'! !
!KMeans class methodsFor: 'instance creation' stamp: 'RoelWuyts 2/29/2016 17:09'!
clusters: numClusters iterations: numIterations
^self new clusters: numClusters iterations: numIterations! !
'From Pharo4.0 of 18 March 2013 [Latest update: #40626] on 31 March 2016 at 9:37:42.371164 am'!
!Point methodsFor: '*KMeans' stamp: 'RoelWuyts 3/1/2016 09:57'!
closestFrom: points
^ points detectMin: [:p | self dist: p ]! !
================================================
FILE: points.json
================================================
[[2.2468149848067736,2.378003715119896],[2.1650033831423943,2.122084074657848],[1.1260092728223317,0.8295179778023649],[1.3309901079268922,1.030296614128997],[0.4702065877997361,1.6242704685249565],[1.8660571025143473,1.6283733610983773],[1.5841297607634357,0.2529206985825819],[1.801773410932344,1.358146424702009],[2.564827696578368,2.991003255693583],[1.1223329911598356,0.5968479785249537],[1.436268801478095,0.36707098136088967],[2.0205484758413776,0.4532181359191677],[1.429426131938608,1.0603650074968853],[2.0760693818417555,2.897917183529814],[0.4114101304189438,1.2403974932378437],[2.0281603058460176,2.0993440156143683],[1.8987334212868778,0.1364922041250609],[2.0397406773295232,0.6267002855059846],[0.5184993789615706,1.9920106433929048],[0.6075775195455348,1.8556833399626949],[1.6859218711899642,-0.0031638097985169367],[2.0491019364026566,0.22487974311251901],[1.9216487191897578,2.698003920370887],[2.4039355120109924,1.3500792365281031],[2.369633464432082,1.324239712381021],[1.2760638259698465,0.4759139633225047],[1.261298780677342,-0.04139894057276039],[2.194045721863355,0.9025346691328546],[1.725777411279227,2.059798094684052],[1.3956013112558843,1.9928036249716508],[2.539460173004464,1.6726371727290257],[1.2794988366477988,1.5716416695146536],[2.54503015600483,1.9232167183206728],[1.1615813734669571,1.5637757471976164],[2.3556689340873813,1.8476702001875083],[1.8204174558528936,0.6051597695287974],[2.1184610992646338,1.8381686057167639],[1.4509835049666369,0.09757217847155697],[1.9725339729836886,0.31086830072935356],[1.4264555945346498,0.9100630701556338],[1.665340759055582,0.44103462233426227],[2.429553769608119,2.088108422949677],[2.0912000876266847,1.5387875636667896],[1.8893453071144979,1.0672902002383549],[1.8636738908728563,1.794328570138247],[1.531161975626472,-0.003426136600974128],[1.702325246788293,1.9617585783661942],[2.6606844358459156,2.6306667832634307],[1.7622937306147262,1.6926983649013982],[1.414868798849186,0.5441259459209309],[2.517651648795261,2.1579463966295336],[2.008600700771395,1.7734494036936765],[2.1813653187589694,0.8837365345692565],[2.206230659900395,0.6110054703705315],[1.9079150132637825,2.8674269343659144],[2.1459935319777586,1.5715616345582486],[1.6863704806442184,0.034490608301046],[2.053502707657021,1.5198555652728831],[1.5488430657859724,0.07514279165343096],[1.964542452285465,1.6781176301952112],[2.15401591875072,-0.10445974525334423],[0.9615387667026111,2.738417551695192],[1.9884782373116567,1.9585096890048468],[1.6172795383174932,1.6524401556847803],[1.1343989581555096,0.7666295877366389],[2.768935051788951,2.8471206393076343],[1.4471334528871873,0.7956777015097101],[2.873458660010609,2.072051126343232],[1.8365677480503506,0.17343168945295462],[2.0818160808262585,1.4505730818198406],[2.016905352679408,2.8384427030976993],[2.413634729155353,1.7735473758623281],[1.4086187075789653,0.02216457683301798],[2.2695828440979815,0.377156356216521],[1.119079501416473,0.7846840435329032],[1.7101119262501328,0.4771403403675414],[2.6017644371619157,2.4145533789377454],[2.4482894133808197,2.0076313431282733],[1.1802102604083138,0.6607381547832669],[0.5673540014740597,1.5196390784276708],[0.7737227976549496,2.3806966567207892],[1.4635077129663803,0.29005086561020454],[1.5016160795013467,1.3223866076012198],[1.0192961999981716,2.037695992819428],[1.1460833083214335,2.0808270501101127],[2.050362278652581,0.6821051383572124],[0.4850792191050308,2.106064688174902],[1.9029497906371722,2.5467394139536252],[1.1948490540815082,1.9198117117267322],[2.333259264109723,1.7094447265294148],[1.9205377811657791,2.017269707580545],[1.11251422854435,-0.027572878301964532],[1.7626098731608906,1.9154853003627057],[1.5507696276273892,0.13893257981620566],[2.2409534053810845,1.7706323612429897],[1.4664843384004236,0.34245006813764733],[2.0124060164176694,0.4774314964639106],[1.2438547144603267,2.1806131936209807],[2.243948814980738,1.7184677773817225],[2.1672820257712524,1.7529064838696238],[2.7029361167791714,1.4812777245699702],[1.9421784358632739,0.35923552126276037],[1.820418549402529,0.3263483398967303],[1.8813665593526512,0.8269883108832072],[1.2591373392871232,2.34353620425729],[1.582360902631663,0.235560067093612],[1.3542635942926764,0.4797845492109267],[2.0431305296669064,0.9480335788912588],[1.395925672185744,0.6016919247776212],[1.9184945598616552,1.804690874498122],[1.7679371803343642,0.051786991051154585],[2.237274404834609,0.1107792321273322],[2.3647632330959834,2.0492789529824718],[2.2552012472169745,0.7839231809079495],[1.5784192049925565,1.8644107426691472],[0.49417813777848596,1.6143852075773022],[2.0512155486219483,1.3360622872899648],[2.097715448167283,2.059970384023499],[2.27361822621243,2.561584992134477],[1.5426138891167138,2.392654938815222],[1.9990515035648773,0.43345215555364136],[1.9593205425284506,0.26524889283988784],[1.702483706504718,0.5498892829599912],[1.5597620648311072,0.48831711082258267],[1.1120622132466744,2.537741421247155],[0.9014991380688318,1.2197090235207442],[2.1651817618757097,1.4412336616085688],[1.6054830493867334,1.5744449698014416],[1.9388406716624946,-0.018837563959065218],[1.6542997459161746,0.7530892925071411],[2.1733437076116187,1.5141316087102128],[2.7659433512643825,2.3037638711414887],[2.00491090538283,1.8671431685906414],[1.7618447760661853,0.9112456406324017],[1.9449442200898235,1.5359951563656113],[2.313486530151329,1.405127360576114],[1.3023399551869577,2.4663962458412283],[1.299555314256546,0.34870251154322573],[2.1155901329050866,0.3354619987498906],[1.3866933023166708,2.1823084526180914],[1.2447759424701652,0.5506515400301708],[2.3869465809037416,3.1893277305003824],[2.151460080737116,1.3792992944737987],[0.8684048919039853,1.975559252565165],[2.214555617387258,1.393301737982584],[1.5067928356012628,2.248428199401139],[2.099239316508062,0.8946732224866041],[2.0075034795766915,0.3967803670671979],[1.210494904869468,0.9426786987657466],[1.6747220772203302,0.5558949156686378],[1.9205992655433417,1.0877098848043767],[1.6688879837376325,0.4831758087204463],[2.4335889572759255,1.891241278295345],[1.3183294659332447,2.2736213453104304],[1.8033362380433609,0.1459786840985411],[1.4051804203457814,0.25122749876511763],[1.9899745886022044,1.5952319614957133],[2.047784747731267,2.9252487793708855],[1.8565023706672736,0.5832211069002192],[2.0154150788038683,0.49172496635161456],[2.184520626742394,2.559529651326245],[0.63490917726866,1.4722838335587594],[2.3914009562778658,1.2856728916035705],[0.6352709082759055,2.6656268746119385],[1.6108545548984736,0.8195348532270198],[1.1158528186251089,0.11382512314990356],[2.3065265731403257,0.8297343382874048],[1.1938986752973673,2.033719562473294],[1.8172654255337186,2.8163472350680445],[1.5064852306027483,2.0926939526767296],[1.0832561902808284,0.5860839107845383],[1.9455755164808313,3.0343947582825956],[2.6123319119092003,3.0070023264582764],[1.6445286855553327,-0.11171749496867012],[1.5739434134872288,0.4414109807240534],[2.154055381998614,2.06395651161226],[0.6564426234170027,1.2755280955421857],[1.4543311838312203,0.18345587968339405],[1.4672973049507498,-0.033022654671062024],[2.0476626918779175,2.0552470954089674],[1.552722326055723,0.4913151060490566],[1.4154109037153204,0.19535676723644801],[1.4701161289609916,0.3326134375285339],[2.3829755231512495,0.8105334874810927],[2.2143970421405093,1.838513524544721],[2.1860659964404774,2.046396213277414],[1.794267372960113,1.7284653106124543],[2.283544380923588,0.6060842642058354],[2.024595112600378,1.672166103807906],[2.648753637143771,2.249751595262281],[1.92731082523881,0.41634086524486125],[1.9679025355017936,1.8727005503540812],[0.6309323610892592,1.6688566703383207],[1.995813218395991,2.8021518987757865],[2.0360954480220315,0.4131202352393831],[2.0182981607012023,2.71829274471384],[1.7674404898075515,2.066849940655372],[2.3274313878576423,1.899490043731295],[2.69792675492462,1.897391410665381],[1.6699174668021082,0.24011475698700513],[1.6755718361098535,0.38456809797760705],[1.8534850096567328,0.6698202874040795],[0.9580343540476723,1.9835312430118537],[2.0877054539648623,1.6477917071227433],[1.4196744263145384,0.3256750185941347],[2.6106646590633167,1.3554657986749168],[2.3367500140308803,2.22826502625985],[2.5056620897542814,1.88917584884859],[2.1260427590748083,2.035601532044677],[2.0053178122348743,1.665015828021896],[2.116814004691359,1.7248598460383435],[1.3609603137909034,0.3573150043183476],[2.795576183893388,1.6254661243764454],[1.5159673125590134,0.4848094840589372],[2.125135016307851,1.9211100748329693],[2.078118620683758,1.337445361095286],[2.0574661763120003,2.2240480199570816],[0.7587063047464577,1.2236883127644729],[2.2367641900460784,2.0320579403080576],[1.2543184634207907,2.3895762749273155],[1.6030771785327846,2.400109346855025],[1.0668548657541348,0.6889355073871892],[2.824340251093974,2.1496439442458155],[1.4938364304855742,-0.1555113770223766],[2.514726342288749,1.3826888333963028],[1.8658779554641352,2.085224269218272],[2.224504509529472,0.9349549233987816],[1.7832202313477192,-0.04151616042164252],[1.7142155698127897,0.6651388678838747],[1.860370202197267,0.01558228289160013],[1.106013044574404,1.0856956658949444],[1.3209167374900859,0.8746923305758204],[0.45291800277701166,1.4603808847706161],[2.6543796970593854,3.149291579102217],[1.8702028312143968,1.1045933003124633],[1.5706233952426465,0.4824383216831636],[2.103077197665421,0.8397477685055382],[2.4395709965488765,2.189852286552777],[2.66043779703193,2.444749512537316],[2.277193305464893,2.3722604692167644],[2.5009083430296615,2.8274234143527215],[1.0266762898634991,1.5431213487417181],[1.9520244662313817,1.8990321131878714],[2.8617110788187947,1.9943295227721904],[1.876206746433001,0.7142618814668902],[1.6013342516571183,0.6374106581158543],[2.4216662242279754,1.393513356426247],[1.541154236349465,0.5121843221969289],[2.0379707681023524,0.2573647885900544],[1.5576644536598976,2.7346824736256603],[0.8138074286364546,1.7149826446947136],[1.7119657614816552,0.9191464936045823],[2.208144346914459,0.3803897536542227],[2.583790985975881,2.938307528734474],[2.2430390870676944,1.931621668746585],[1.8644266170179884,1.382192843643401],[1.3726180053317232,1.3749427946843809],[1.7006841455515653,0.41095419978245284],[1.8016708410161868,1.7060500122427977],[1.9141515062629306,0.2806505709107009],[2.2133939485081284,2.395992954210555],[2.2739042175377757,2.2202367815465287],[2.048009631596683,0.5775194135290862],[1.7358276006487254,0.6399591481919593],[0.6703680197585344,1.976823662836963],[1.743147653205339,0.19660873284324032],[1.4569966066073854,0.8925274714350258],[2.6918385247084937,2.2441195838141286],[2.0314681297838773,1.3763687410788497],[1.0782164946047215,2.0641140400395637],[0.7479396297057531,2.3310968625422435],[1.9092661163469187,0.776923685017059],[1.0995804926715733,2.1947580789208962],[2.1928534122473984,1.9846999884582215],[1.4402141183435175,0.23944447593005203],[1.631855314156542,0.5445085108223092],[1.7520360282827663,1.330896142038761],[1.9926845808991258,0.740811690727408],[2.4352511822006826,1.9291890522526305],[0.758728758170909,2.062177713946112],[0.604845263740586,1.6611528285082149],[0.7567704868417546,1.3607169279497544],[2.004066678676093,0.6230937822092782],[2.1327056871074994,1.4659842900889568],[2.182785235586079,0.936146651196243],[1.651423146562333,0.21091710766116145],[1.9910462569203937,2.207892588635053],[2.3595259385096936,0.17325680362590012],[1.3566212981783317,1.0724923430058735],[1.8090832778541337,0.1109318595711225],[1.8617283974238539,2.2154700859225587],[2.1693288448588803,2.226184174292409],[2.209916630952044,0.5879340453614454],[1.5475344386773673,2.1700883998333995],[2.2258040513362007,2.1907304232685423],[0.9175450822260923,1.8026175787799699],[1.4868994262696305,0.6452885112777952],[2.4916439329706384,1.873627936557444],[1.6736594357311092,1.932051695775788],[1.2314810314602607,0.3383153227411483],[1.5920345755455654,2.2420383150147494],[1.0667117968737736,0.18674829386663327],[0.5345536560787771,2.037662542874662],[1.5319284182061548,2.4239539948078983],[1.7353032964479196,0.25423927867051943],[1.303841257769873,0.32210863858202854],[1.9082793826843512,0.5089826637791697],[2.246783584839709,2.9373870323107503],[1.6480502644721111,1.976214815365471],[1.1474246769507397,0.602614870579842],[2.149931908130477,0.3260130980622693],[1.013955167266624,1.9438126656984218],[1.9249439505427426,0.4554502921865856],[1.4707607736111332,0.6668570752027672],[1.8899385226890815,0.3548021163418579],[1.3042825809467016,0.8446960052095657],[1.730016732430125,0.09275933884282561],[1.5728944946756895,1.8813203619013152],[0.9903205920286063,2.4503382443487065],[2.074084647811796,1.4884653664592624],[0.5149825743576346,2.161134752721881],[1.8231253350501286,1.3573996876149446],[2.211911668185537,1.743560027793323],[2.4587131833601337,2.39889928981276],[2.264964214102453,2.348309993506982],[1.2652848916416461,0.6020446776608299],[2.2857061384726,2.0902851375316485],[1.4931043076553723,0.574571176873252],[1.0346959366501451,1.3380045512773258],[2.3281670956048393,0.3459322844751621],[0.7258429374586104,1.6525207902937837],[1.9915025262797434,1.559802893368938],[1.2436920396235203,0.936482861364889],[2.2339898364171056,1.507192157638877],[2.23238647091753,0.42165498326003525],[2.300333555752767,2.147025534950601],[2.1065928472838102,2.2233232655295465],[1.092149268922112,0.9438540104960595],[1.9304119235521213,0.6256406243540356],[1.3416091540890562,0.5535332583433138],[1.4953345642672196,0.8289195522422425],[2.047460121881761,2.0814064719470524],[2.192544571159477,1.8681796186380917],[1.9313389085194914,1.24986934786571],[0.4756638710265988,1.5169536263650714],[1.944233571501905,0.8409216598068923],[2.2631179750448744,0.820293826103383],[1.8911865793648373,2.181770354111682],[2.5002722867252833,1.5464843139819675],[1.5793477205844164,0.7110065796749181],[1.8964179339531706,2.519443606725699],[2.252229119545232,0.8386287148210663],[2.214389048942783,2.875898420379127],[1.324415407127268,0.5467848720115539],[2.348377611259928,1.8116162794635335],[1.4995586708470228,0.1534117466165863],[1.8814192102240983,0.5147490887619338],[2.22564422196251,0.7185548077832973],[2.2433770994501088,1.91582794510182],[2.0467767609027248,0.7081352255905541],[2.2904285348175564,1.6436170875414597],[1.7839629844285498,0.30899934217868086],[2.286249415723163,1.665713172295526],[2.106378411772567,2.2651298004911116],[1.8127961062831397,3.1718152584842807],[1.8632488184630849,0.13119831526965775],[1.9233897559667121,2.2409400043673418],[1.3519519639360231,1.562388522022427],[1.787208463349383,0.22041839460162183],[2.4054252513609296,1.780700446956501],[1.361435812674274,0.3877845778810931],[1.7134784334794446,0.37118763515647235],[1.8177370270132207,2.517089739513931],[1.2489171259275866,2.0209994169961814],[0.7943187907058519,2.576338234077124],[0.9315581528426969,2.121889165465583],[2.5688561161831336,2.799409795381849],[1.369962583802251,0.715145081593235],[1.6144305531980971,0.023387552947543466],[2.052035072350966,3.026119198706553],[0.6697990252369109,2.39411707895518],[2.4258969904989867,2.220362887553509],[1.608684575269653,1.3031344216333203],[0.47867715949817924,1.5611178389727072],[1.9513142033044364,1.0368089148283262],[1.565392232330237,2.7171097475245283],[1.5181022897688905,-0.08153554349621228],[1.6459532871194227,0.01070621397898075],[1.1229036268252024,2.6911448605522446],[2.2002117955852665,1.4760970451110307],[2.3986178045847226,3.0049303881767697],[0.7987749616410891,2.156219447156674],[1.8401168562411945,3.053391749596811],[1.3880901737263796,2.001019542377816],[1.4573581026221298,0.779561727005568],[2.678902858967357,1.8492395635405],[1.4780392844992978,0.2791992177788729],[1.807635230683804,2.27488905585093],[1.3549634496120717,0.21152725641047243],[2.040219730063165,-0.12058077920818244],[1.8697641669574137,0.9053347753671174],[1.8277069531430117,0.6622518679878674],[1.950713463645657,2.405338385184929],[1.7317613555426237,1.5035106370452451],[2.170849795923236,1.798069277952838],[2.757824484303704,2.05242818550852],[2.174975460122449,0.13095708235035575],[1.5257693979314007,2.1573122580834676],[2.3324410981541472,-0.016108835783421704],[2.7431001518459324,2.982218458059744],[1.1548896706334906,0.816285204702944],[1.28218754419443,0.74073286125451],[0.7835414436041268,1.7322124016245157],[2.0139426316646127,0.7091622289048087],[2.4950753135170167,1.6681618737361097],[2.611531200820287,3.1432121172634195],[2.008636186947002,0.05425711231214492],[2.1874005543870636,1.3261400615217744],[1.931564924448121,1.4030881440220075],[2.0105558304325455,0.39086537296026225],[1.5086602453724662,0.21363777146726615],[2.3556822406164115,2.8026602134888563],[1.8902446953779908,2.499043247182838],[1.2211922959613166,2.381567005056962],[1.677733893585696,1.6614954550335486],[1.6406523906446946,1.8225515326575457],[0.9200561784285478,2.544605808050169],[2.1233969843272016,1.7519081815268016],[1.1462973465235184,0.341002579150529],[1.3305483302403358,0.4651484265997946],[1.1311168420314424,1.1315424492254318],[1.275783343162387,2.0491828868685373],[2.1433193031977176,2.0941051914701196],[2.1970620153354963,2.2949645501272258],[1.452467217997334,0.09379539458106145],[2.805605844713509,1.6154627546706044],[1.4078572380904237,0.5061099305773691],[1.5822395004897472,2.2907184926626707],[1.468892787734434,0.031074153013726846],[1.7318443956321392,0.27705361385218974],[1.996136760637384,0.6010744657897011],[2.31133353459668,0.1926971267448926],[1.3462119389272058,0.3833332932111235],[1.9927617391398327,1.1816866045619847],[2.2673835361268484,0.7160937316115366],[2.8454047205810826,1.9233710528130294],[1.886825208309858,2.412058090233021],[0.793700114828028,1.802223275754118],[1.4275245804639392,0.36061904493687225],[1.2211586479441183,2.0302465978454878],[0.8069927438088556,1.9012190793334574],[2.336206158718941,2.1571143565142914],[2.674517188496635,1.6518048036969275],[2.5036627418175224,2.181721965041838],[1.7939800585443622,2.798212586308917],[0.8760154189508258,1.2301272165769506],[2.3195643833445714,0.2531824963406273],[1.6451012509033824,0.5915773341831989],[1.1568610541478634,0.6988080110290992],[1.9626340662743487,2.0737476938916486],[1.316451119924914,2.4804681927153944],[2.023282706186807,0.3745348216827997],[2.153613594698473,0.538807478606952],[1.7742526597795338,3.124098573305624],[1.3232501059872115,2.3648055443720652],[1.9766419177013197,0.4880738868743433],[1.6889466799653747,1.025680942487615],[1.1527671982394392,1.238730210932815],[1.7251973841312014,0.25713122695679114],[1.091543270568633,1.0274980509747578],[1.5950410453825612,0.08681308092606377],[1.3902852617597043,0.23368848661238895],[1.492633911946753,0.018128209258432615],[1.3477127753312563,0.7404846049809557],[2.320665388456649,1.913762920166386],[1.7629299341686284,1.8127682875130755],[1.206061857411459,1.5531967927233437],[2.0527581863839925,1.9462101274871637],[0.8705287389847679,2.294662851272823],[1.7166455041202546,1.3769024345050047],[2.2210994071606467,0.23569843867864249],[1.942943647723952,0.718169756092779],[1.5803993116193178,0.3891370494778966],[2.559436054797092,2.6094445732401903],[0.5089068274647756,1.3987098349229252],[0.9247742713014552,2.1452763391821588],[2.31483995999827,2.3134210903475703],[2.490428906949033,2.2768857420144366],[2.5667460810250056,1.3400399670443681],[2.756266908515777,2.1626295838570804],[1.7559572045737941,0.9417773999227648],[1.476763587347333,2.398163089728894],[0.8080003310789955,1.5734702380275327],[1.4604786706953572,1.0961295364097745],[2.7572815181143193,1.30806818067229],[2.274419296121006,1.8306544278240535],[1.3749175180524635,0.018923642454745315],[2.4535840071980486,2.274366284752832],[1.7079062049014215,0.7534544572515114],[1.1011157932748186,2.306264648061302],[1.7637009305384246,2.0820886410266755],[2.0295951743544816,2.57812441297506],[1.7117106877943016,0.5698240719204469],[2.4556331878618938,1.9098567998426144],[1.6778908298272062,0.47982735795268994],[1.63098208816921,0.6106906760480763],[2.4496221120790596,2.553934740646139],[2.004342197993516,0.18166868674926473],[1.2609650864486355,0.5792644322472477],[1.7831427990200952,0.3189419416326469],[2.6138665760705706,2.28342062815799],[2.348770632218398,0.7699361643574798],[2.2246588823602726,0.021997187798118212],[1.8781995278223929,1.6362717006531082],[1.0168412030366403,1.7767074033994525],[2.254148850410202,2.2850712570902765],[1.7374902518458617,0.5406788362933752],[2.3173719357266176,0.06681265195073605],[1.1733859947790308,1.037460832858904],[1.4313533608236877,0.1429908488931657],[2.164692363550625,1.7060973375220605],[2.331433416770401,2.0567612121875],[2.5045523570126313,2.918386872275216],[2.358099834545896,1.6186095941581056],[1.7016648426062104,1.6249954926149686],[1.3885554470298467,0.8838111799833872],[2.8725133537052443,1.7045566675911226],[1.7598877718099937,1.1651920837356315],[1.4806902696837443,0.7270852513177964],[1.5931713217299865,1.2300131117268354],[1.7779994075712748,1.7910673271136872],[1.72053126038891,0.3166211223511305],[1.5612602287449255,0.7012486472141081],[1.1961693109472105,1.2719222867962399],[1.7113311020089776,2.338897521418486],[1.6644931748047016,0.8766717903496929],[0.6702863424153318,1.969108324801602],[1.9077646908643073,2.4196560007611088],[1.510716674409591,1.0610305073533257],[1.2358263681136403,1.825721452663537],[1.2426643032394065,2.5619130781289767],[1.2717667374793513,1.9084799802269201],[1.9145709792081869,1.8923339997267377],[2.005390338690964,2.239814182430199],[1.5065611621034287,1.7226267597121727],[1.8556725174525233,2.34797709568801],[2.917059067948803,1.3629282200700268],[2.0473943432196733,0.6306317339404428],[2.390284124389768,2.951910063836375],[2.0847934123269027,1.5675150462826797],[1.871903356597689,0.3047520619035953],[1.1496651540906613,0.11033344533232392],[1.494809289073931,0.3946850318356744],[1.6502886214397232,1.1811080324070131],[1.5570635328781293,0.19027260168694582],[1.4544393319610593,0.32801423335731483],[2.089488073242861,0.35778200138976335],[1.6992172603909297,1.756468679219696],[0.8800372211556566,2.5331192015277186],[2.090491915197707,1.8445526775255234],[2.446799709256371,2.7931814250673117],[1.3752040875483085,1.105196939798987],[2.750102665538011,2.954130500706497],[2.247414347003995,1.9757383564490647],[2.4621480670638194,1.580654085488722],[1.5977137802226777,1.015096235249679],[2.155521743152747,1.7033764672240541],[2.689536008878373,2.4244848599900157],[1.3735498224785392,0.4093122003095869],[1.8368108148570168,0.42448214266932893],[1.5472042907860446,0.14302583133599267],[1.4314627118742047,0.782410594487935],[1.7334528814045997,1.9370967331007214],[2.7534143876338737,2.2213263035069524],[2.1882698867034804,0.947127114401876],[2.198143146478188,1.6367169214750756],[2.2147997086452573,1.6850038380200199],[2.2702466604802822,2.968333084664455],[1.1109206337743378,2.2968919116218096],[2.469610845705548,1.4809534171634686],[2.1406089992695607,1.80391971841413],[2.4859828045061265,1.9082102257884759],[1.20509150363323,1.926853425862059],[1.9473958711951669,0.7658963297241702],[1.0331553810843075,1.29007960164719],[2.132672643797177,1.697097833693186],[1.4324621606001124,0.4817122468896484],[2.0703752948318557,1.2375462140054605],[1.0594363084079106,1.2268667466857655],[1.7822419194353116,0.31930762184492567],[1.8132125883159815,0.6369087396522962],[0.8680055257014395,2.451590461636879],[0.882238017314755,2.082777835150489],[1.5807257287197218,0.468811762026776],[2.1731696147470183,0.5641997239515402],[2.6935449651990826,1.899477859070931],[2.159758931041967,1.2951299424152323],[0.6837346038858919,1.9942412254799342],[0.9168649159439298,1.4908663175326504],[1.7337285991121067,0.6904422240993946],[2.5493160205831003,1.7727763428676417],[2.1639757516450535,2.7430509013254776],[2.1692284919518983,2.0086287713749953],[2.438140419059644,1.8526322433390683],[1.0127766346058409,1.9737464889338],[1.5479309125425762,0.6877842898144332],[1.943963831000874,1.547970740377702],[1.9698492508849648,0.5981417921781413],[1.7846090041261355,0.5804846779014003],[1.9081126131987953,-0.06743132599325086],[1.7947103250742429,0.4291712630513953],[1.5412369357579219,2.32930782402831],[1.9728231586264249,1.37489684094345],[1.7873423020596575,0.8809351987988627],[2.057158902229377,2.1603059019606876],[1.7134641957463432,1.7337566600195977],[2.8582784079870067,1.9614395226380348],[2.7168013494101633,2.244555985138307],[2.4672340373807677,1.295903828871071],[2.5732917059483094,2.5640218459254926],[1.5120189660672043,0.0521166045117214],[2.270558143016784,0.551604206020647],[2.1804796071734747,2.0311997581376344],[1.6559812390173587,-0.019081973031856214],[1.3903271663635608,1.5899555974867239],[2.458667833827787,1.7769154640298503],[1.8487197677965632,2.0696226141139626],[1.3660141208876408,0.8633709394163506],[1.738376886845134,1.4531154714493653],[1.9884861007104164,0.7795012521283192],[1.9871810910097563,0.8737804098827661],[2.003624014786564,0.07482151158771677],[1.4644541882829287,0.27619104358063473],[1.6964352845806463,-0.12324720037009784],[1.3581473463793916,0.8425652071043832],[2.2974477372940547,0.6120870975363647],[2.390099860201318,1.991843347909262],[2.5962777205489065,2.2129297913284036],[1.4138905451847599,0.604876427769523],[2.404694855161923,2.3018256954275853],[1.3952376859991629,1.8928421116345673],[1.402810820502284,-0.11006444958684602],[1.9606055472312722,0.41509996314225095],[0.9622256143713896,1.4681645698233885],[1.7295903722799792,0.6249862189072312],[2.413234839999001,1.7191670031621666],[2.290781006694884,2.142135940942605],[2.0357798616477165,1.7664160258142148],[2.1102698582810873,3.1345559494850024],[2.3989917062666284,3.147310994252],[2.361530822680295,3.1652439983732035],[1.477145872409852,0.4884800016055709],[1.704169458634839,0.24030394208468708],[1.5182361148978192,0.23248961323326633],[1.8628708268669665,2.3631902371694524],[1.8870698993598476,2.508516290429379],[1.127083052589732,1.5281473413566609],[1.4793930609779544,0.4637176897137505],[1.4373474642002173,0.2563282031098225],[2.0069838728345886,0.4355558798123885],[1.6993214885374315,2.2286962033191515],[1.9917352028056357,3.106650582018727],[1.074962624596885,2.5510995007110115],[2.3181808373916954,0.6977745822066088],[1.4436015359792833,0.07834581266895546],[0.8387171076211387,1.435914643467601],[1.9710690572588272,0.724916316043002],[2.8069668016278397,1.3285825676387208],[0.6492076943508243,1.3726482207288662],[2.43328441156304,1.8166430205518354],[1.2775603228180046,1.139866707753086],[1.9064590005034536,-0.12839932728269932],[1.7159230037383422,0.07615161671136561],[2.3320072597853914,1.9774836015993995],[0.8403835824643006,2.7181552078650433],[2.2265853842241534,2.269624795926797],[0.9424131049185155,2.6191673326740252],[1.3475256322046143,1.8968373728514587],[1.812251138147952,0.4305042428958863],[1.0613954774575707,2.130578995794321],[0.5941582571980865,2.4093335524403705],[1.979399959199442,2.680727433257338],[1.9688610774047273,0.6817790726406718],[1.5291928551699008,1.9703773917058705],[2.303854318722519,-0.12862173219125628],[1.7049101562775484,0.9209999160780232],[1.1154495731441783,0.5284811289440582],[2.267663066964628,0.453607961837198],[0.7766551888355192,2.6414591459979513],[1.9656943883962446,1.5076718572317467],[1.5149727449562485,-0.03301821397074445],[1.9774872752454353,0.23254911325408623],[1.6178037675150356,0.7117940119851843],[2.442102277300978,1.8556918894678402],[1.8023527117634504,1.529300478384919],[1.445527314563921,0.7133181605573793],[2.084365290501036,0.5999250813295285],[2.3432500164562557,1.8742801394783135],[2.008126906737594,0.6705009669949504],[1.962474907492155,0.200866263062363],[1.4427301647866608,0.4028548671425698],[2.0467396954831485,2.076748047384789],[2.1679351751509115,0.24588726459277221],[2.3627197475780557,1.9343839701388248],[2.2340249975409745,1.8252171249954443],[1.5155325888375883,1.3609155618345798],[2.399643416012245,1.5722615925476566],[1.5288532261259715,0.5166267536792325],[1.9905744015306177,1.9147693674726303],[0.6927335557307257,2.0616306463269805],[2.4858675483394634,2.136590126089755],[1.334737981843117,0.6452902432810779],[1.6314145044316715,0.8026240719348147],[1.8490145088985317,0.7445720234295619],[1.6174459109855173,0.4288943914917097],[2.4713454692865855,2.2348239910160115],[2.5481233302428126,2.251109594927791],[1.0126411527128947,2.094833053022514],[1.9718021203564944,1.8113497839727373],[2.4304178212434993,1.181758491876108],[1.6854134393238445,2.104554885734715],[1.80134468028906,3.168810986005369],[0.673593033490228,1.3187242709299387],[1.4841626961912817,2.689420667545197],[0.7291359626946871,1.7325942219466022],[2.2088313561089303,0.8163704605192736],[2.436381297795961,1.2947726425346517],[2.6759359115832413,1.8160834324748396],[1.1257469970574445,0.6687606265197871],[1.1375131332595787,0.6297596640533631],[2.319502672758846,2.655976489065104],[1.8539982032229783,0.3185778014345746],[2.262917078101835,0.13205545168310384],[2.3380423185669366,1.355732351623007],[1.7946662286047974,0.015143586548098886],[1.5986218132445713,0.525916454659242],[1.3844994712390442,1.7102833283143513],[1.9060087286711194,0.19879985595726812],[1.5474035931639294,1.0721297091328792],[1.4175756741416246,0.9166508202226711],[1.4585386709392996,0.13698851173293147],[1.4144318944952714,2.2761866551490924],[1.2820456682388586,0.6501750104224185],[1.7423352237437868,1.5404904245903066],[1.6720963921003316,0.6520178369359211],[1.780394472229255,0.21945789602156807],[1.7914157323529984,2.2195156463663976],[1.9437451151843081,1.8436427805054496],[2.7615362670882813,2.394646942510612],[0.7166991073896445,1.4613536784341274],[2.3401378177726975,0.890815413544185],[2.3278211887537643,1.2444658302015248],[1.8327034724820397,1.2902131138463795],[1.7254261052967288,0.7459424342717839],[2.511381045700655,2.260492507698131],[0.9337689820790861,1.5502153848822755],[1.9565254328452855,2.372401718095314],[0.42322522751999847,1.3026132473476877],[2.575852710569956,2.823476695386663],[0.6605609395348176,2.1329178482213385],[1.142755264878827,2.2122952986741313],[1.979220384155369,2.0767161798232214],[2.2924687539973934,1.4997274708771275],[1.9755191222419675,1.6538475374908765],[2.061610641673693,3.0016067192733367],[2.7517346642263205,1.4088015084556524],[1.9723843035231075,2.8180354142558426],[2.0487385724841416,1.542180756312068],[1.823060426866609,0.0832264820363191],[1.696104359519452,1.7990303860553067],[0.7035203876053979,2.7193774362155128],[1.6908132648699863,0.1843845631303953],[1.777247486849872,1.7827309312501327],[1.5858924855108902,2.03294121692326],[1.3078556961375165,0.2632377536715884],[0.9033761614028838,1.4931583538653523],[2.3946961104759055,0.185597979158594],[1.1318251554360639,1.98662211781612],[1.8134269328405503,0.38154240801746864],[2.016970465617134,0.9439780773219023],[2.3620176543262392,1.3992742391418873],[2.3462437651611503,2.9469316337293057],[1.5351665105638264,0.5940261301377829],[2.097151267285547,0.8628610925476446],[1.9422726483236796,2.2107235872433204],[1.152120971914203,2.04207255540849],[0.5680982748623237,1.4274267790353412],[1.851952899262006,1.2587914659914157],[2.0496568853949397,0.7343596172339688],[2.3376397714327832,0.7907512359684947],[2.375433163020893,2.0595379796025783],[1.3813772477617081,0.24914491901684088],[2.4515765114579238,2.967278688410285],[2.816336567782865,1.623045324068894],[1.8675777317741562,1.4628342020565688],[0.7756490189646577,2.10539374887548],[2.0346359557791978,2.3403403518081087],[1.585038952325859,2.0602266804368163],[0.6984096296963532,2.0317179903818956],[2.8866102555205577,1.542000141822964],[1.8562886906150986,0.7005780690227608],[1.4628475431329884,0.22044436861925665],[2.888491789569432,1.619858250050131],[2.1208923441473484,0.7096713342209071],[1.5385810978793817,0.594331521707929],[2.018160908442756,2.190255937470422],[2.374149360451516,-0.005042635708550902],[2.007260512141332,0.5522883306456606],[1.5459307523696268,0.6695178969408077],[2.297345338888542,2.4832726853999953],[2.2815460815693074,0.48413643863031663],[1.5740374978270038,0.5243281285145359],[2.1165495699197447,1.9502885383996913],[1.0791541213062419,2.503153900295599],[2.8007287631951097,1.6176870614581522],[2.093386853634562,0.4442386463064425],[2.0186368683875715,2.9851779540056844],[2.312817951808238,0.2451283499728385],[1.9888683916581908,0.276070551698144],[2.451244837148008,1.3560797723600162],[1.2561131501568688,-0.054218059235453864],[1.9392873960553239,1.794145334040175],[1.2326849162870244,1.5131855804585552],[1.2794054291129842,0.6856597239743585],[1.8279380819276976,0.06599327419118894],[2.2913744566874747,2.1046068533481854],[1.903815991163997,2.3499238348032168],[1.6970260801302233,2.1447077049984014],[2.622861219197723,2.3507654105407934],[1.9701005292361105,0.3091400419576926],[0.4827021269238325,1.4183979499965185],[1.3525510924427326,2.1747951344091234],[1.5004701470450734,2.110432617083207],[1.499864482804103,0.6667747688006889],[2.4360193437929,1.4873000581448776],[1.5839598635022416,0.20451988659052633],[2.2359038937118276,1.7094041111366969],[1.6462601138807245,1.3484753860770553],[2.0348297750686415,1.2923665308741867],[1.4200137970473916,0.45189700895663665],[1.5219419508465715,1.4858095351385256],[1.7840652840512732,0.303113543756487],[1.9529255767308178,2.2101584997082124],[1.021945920470038,2.061556654911805],[1.9832229937464667,0.7765895538347065],[1.5799413548930517,0.7098950343711089],[0.6465470390895934,2.434331738688782],[0.6850626164717912,2.0531127854918507],[1.0280934336236212,2.644492735606446],[0.7546593187405597,1.986162885968894],[1.7897990739052712,0.20743129070557542],[1.3808860879037055,1.5994586117083458],[2.3080685347273544,0.6735679822139875],[1.2008838311052843,0.6006760610719287],[1.5611851548793707,-0.03632180303650101],[1.5446616883237807,0.7929477337869091],[2.4050607404399944,3.1150368093331995],[1.3625524606363923,0.58649305499487],[1.1066748838603373,1.8690615045255594],[1.7219942634270895,1.841934462526356],[1.7324820840971678,-0.01773039846500757],[1.8240003572110401,1.4719853323938579],[2.142397130192703,0.12687101461189954],[2.886856903216675,2.128232506540943],[1.9206591886832192,0.38689019795953317],[0.7446896953524716,2.3199482230817408],[2.728395302608032,2.2705870410088256],[1.0670356305852025,0.813207973882112],[2.4102490205665563,1.8560671049285902],[1.9155786466162454,0.7806287908872648],[1.8518882894225437,0.6649353486101534],[1.2087907178221893,0.012732719855705121],[1.0054120990616342,1.9297705327235724],[1.8613580450162805,-0.0837528912891925],[0.4724413969529072,1.5062742357378602],[1.4290756820169206,0.21681325683126496],[1.093273150364653,0.7937508473735801],[2.648149063813339,1.6056527546730877],[0.6555042705367478,1.8919488553658137],[0.998533657223077,1.9166549986976587],[1.3988359378151105,0.8157257674976397],[1.9948174866169643,0.8660246000616069],[1.9053245716399172,2.427312055592254],[1.8532550886370034,0.403754748485858],[1.3352052488885287,2.056212321400566],[2.1514588650262736,1.6878834259227486],[1.5220485729661875,1.8009088690904467],[2.182600295486596,-0.009393378736443525],[2.2775275077373065,2.0008715682313687],[1.8715326164441377,1.7306034002062618],[1.6102610793260501,0.7493038327677218],[2.069628200518667,1.5250909322519042],[0.9258779773519942,2.190474757479906],[2.50315352452145,1.7153648616157646],[0.8553943487600235,2.0145333685469056],[1.1861811756522727,1.673539351677526],[2.294528603480505,0.5308159529114326],[1.3278503277983567,1.9728096604613725],[1.6901349886421229,0.7266850763013167],[2.256584991265472,2.99039013324495],[1.9763410608098324,0.4148591257268883],[2.237868178981824,2.0637820759008774],[1.6963165581665687,2.1218221417589858],[1.0192957263084783,2.0836609969561586],[2.1354024516363985,1.6718134155932431],[1.8365280104600938,0.9129053769627543],[1.5507967690764366,0.8011500683197218],[1.5526145706403922,0.7077168288975955],[2.346457296969716,1.9524914767921548],[1.7542309758722783,1.7267893361435147],[0.8078850380946554,2.5283169002040218],[1.805327467977556,0.7895389219724123],[2.151068385986934,3.082647882317956],[1.6962412892205636,1.3778317412422556],[1.6171532578518801,0.40163261111067816],[2.3901839229582524,1.8476934998639454],[1.546506042757907,0.4102271224528997],[2.167013555557596,1.5234127808810034],[2.3873404453505995,1.581050194533145],[2.3448363025576318,2.3705376377251652],[1.5868565005698145,2.0534972417369515],[0.8399874240993581,1.3316573282669757],[2.532870365367909,3.007339468634257],[2.338543243430438,3.209650333642654],[1.6738837573577077,0.2447411483246592],[2.720474726713462,2.1915619974448415],[1.5106820470861555,2.078180939253817],[2.5299700383554073,1.6542038393926477],[2.0008217076644033,0.8906588731231658],[2.025741074193448,0.3476073164249259],[2.455206364397343,1.465522921976631],[1.8300394095103534,0.40964210463961737],[1.7348575981788854,1.7617603735242207],[2.115677828031314,1.82317905069221],[1.1509905451520992,1.4088486701455394],[1.3721400778896808,0.3624871445977037],[1.47374140457806,0.46700922415261104],[1.9728432127675246,0.7782612066932167],[1.4949046097395382,1.8747651520582682],[2.2115912521240726,1.9829851345847576],[1.8093246220001546,2.889334265621619],[2.200137503260213,0.33662285611315823],[1.4961382221632875,0.863677475342014],[1.2553034515300743,0.8354425792960333],[0.6554672704186313,1.8400556125981695],[2.1775105962965573,1.7471607991183777],[1.7123984151109604,2.2328534033848064],[1.7970236393052734,2.714676376492951],[1.7410424594265463,1.4855111218805586],[2.3010240327538503,2.126233955487447],[1.9182133726133752,1.767391298687858],[1.3454915243099208,0.5223948494540585],[2.052183423338713,1.3360168418502647],[1.5557735162203106,1.6396234385016593],[1.4543156955024408,2.4305614594547458],[1.840680919389782,1.206552340351739],[1.8638089520382053,1.7890221011418834],[1.3622086270646534,0.571588227300189],[2.2079204272055826,3.0110538006661582],[1.9656548532316012,0.8746488647089481],[1.3961793290311235,0.809443310568441],[2.384251988099273,1.5792555674944366],[0.8702572245086023,1.8537271906965638],[2.056567069843773,0.8187166383079609],[1.81517550396569,2.81848390816308],[1.5298210012701396,0.577877288335949],[1.1199666960062649,2.0666975162955774],[2.386292426223991,3.1384959634942855],[1.4362702844553565,-0.07617971824361236],[0.5651477837729377,1.631700603288107],[2.1410419957753186,0.3508100812757121],[0.7369767715953375,2.3711944863774197],[1.4456184107079837,0.43471337304818225],[2.0381831127113683,1.7761286756298515],[1.216146855000766,0.5126660318303174],[1.2853009709060306,2.5153583680027296],[1.4846015996699737,0.1379445890294534],[1.7630376247298838,0.6378764637182797],[2.724257957948131,1.8185312770073567],[1.5888601943531886,0.3130613035181513],[1.1150502937753077,2.5332037348979948],[1.1154301421680906,2.1929862888650065],[1.9293547194344027,1.1707758115602616],[1.9212225898610464,0.7952650339621458],[1.298964346494504,1.3082792081343837],[1.1030723286559374,2.2442105836093846],[1.1645620605443079,0.19755562969726004],[2.3324175333808346,1.5919503007276525],[2.1531340212813976,1.5608069633757355],[2.1482248527911203,1.7483121072111465],[2.2264606043876882,1.759199384165894],[1.8425366436485735,3.1096046763356786],[0.5345354462326395,1.2102069870660512],[2.5172341254540065,1.8000429207396653],[1.6758112765142865,2.010404863066713],[1.5600366780823647,0.8530759335534972],[1.0036163903913584,1.5309070706173342],[1.4307442973279567,0.3463099533297772],[2.26456193319139,1.6631561186330786],[2.054519678425259,0.5877235907699979],[0.7702316588876995,1.2671910405807738],[2.0342623777102506,1.8311679178918712],[2.1601162002076553,2.0470739828264284],[1.7968636039975925,0.03252691444664013],[1.8994739131492269,0.8694629640060904],[1.2272056129491278,0.5615006916184473],[1.7549149532739388,1.1861218288574054],[2.0417602118624725,2.767645959268494],[1.4576285447557291,0.5180838650267855],[2.11502714882299,-0.09179719306933287],[1.5321746942844507,2.3981669917535253],[2.3405143289276458,2.689795922135383],[0.4806517413685597,1.5130460779448236],[0.878511962791789,2.5181576057114055],[1.334204850773458,0.6778058043651705],[1.1175389608319328,0.18668932359426216],[2.267110762012675,2.0595956520338534],[2.190090884593837,0.2696359633595976],[1.9461264304377028,-0.012062754023053568],[2.634631216872913,1.7104774722425713],[0.7719453784866087,1.2559532038649928],[1.8166737855218635,1.11013801086743],[0.918188796733922,2.647004967984932],[1.4499634287947005,-0.018725850323641824],[1.562076614500402,1.4244219995875227],[2.2912873939787612,2.6605114608248734],[2.1133452311160044,2.4424295131749143],[1.1050876871578803,1.9970356178947095],[1.46660421271238,0.8857757039863194],[0.8442057135755772,2.463076849783955],[1.5153290110811888,1.8084115932177554],[2.054408938074336,0.3543377804658362],[2.1230747912804144,2.247675257043535],[1.2096187426926188,1.860748789218332],[2.4017840106506743,1.7067916059216166],[2.188672216695614,1.9543128446467635],[1.165853021666777,1.8050718152335887],[2.4592087213507536,2.0316086389279597],[1.9695630876900299,0.827449436696073],[1.7885899388736939,1.1862447648410304],[1.7399940836040853,0.8304141008755217],[1.8544189879988542,1.7984998157413177],[2.0160615885928572,3.140951826748821],[1.8875427911049472,2.186720044710885],[2.4853221826587046,1.3905927412731898],[2.308540801407755,2.0481637970174185],[1.891873312347288,1.429287185455692],[2.118572553516978,1.4944634602698152],[1.0197812386906784,1.3869102795389787],[1.8799729426459906,0.8418191242423687],[1.2610411944179303,1.905739874776438],[1.5257906586287322,1.426605679127289],[1.3555267628092114,2.5541404605327256],[1.2823314907254975,-0.10514914714889056],[1.0943946108956348,0.5646134416741978],[2.1383249389754284,0.8646496752524025],[1.492992386980877,0.8112653688889437],[1.1222191601277636,2.029703212325349],[1.2029109915477663,1.917989367953266],[1.8514216522539821,0.40348278912702884],[1.2547727379162397,0.04247156973822808],[1.793966992336458,0.3569997756722437],[1.0829387025599275,0.5316027205539605],[2.5419830679255195,1.3949849871832674],[1.3275458840538916,0.8476874840056468],[1.3613963335768489,0.6199543415536176],[1.4738953895508788,0.30462574784648744],[2.279091249097731,2.186908993561744],[1.0987716210002358,2.746590980904523],[1.8346993639528626,2.0115222015367102],[1.8517885651076413,1.9529330202894977],[2.423196248250778,2.4296835528027487],[2.2218584846660776,2.373001193572286],[2.753212925773397,3.1335221977052488],[1.4799741053531474,0.5901327219990566],[1.9490931986555102,1.9398696502032209],[1.68652340388857,0.19473853668719365],[1.8152334692994696,1.4371439280575162],[1.0564809989141066,2.5155989305404036],[1.6915530021417617,0.2636716258914371],[2.083237686565825,1.5239535963108854],[1.2359820527418601,1.8644788689277143],[2.3969188752206603,1.4234585379721358],[2.2060776370581414,0.07622267548011596],[1.9057396329967211,0.36072939963676665],[1.3397984743831781,0.3331358546843989],[1.8139409323026063,0.01119916748827654],[1.2305404651024032,2.7512195341009456],[1.1668135983836496,2.6625861589359916],[0.6640490956696933,1.7864128853057508],[1.940268694619662,2.2893434679658227],[1.9547246956554778,0.18720636885017639],[2.323211584175556,1.6391992922956087],[2.324881126939746,1.7612690609774628],[0.9559232937453416,1.5721398110497646],[2.07576540657216,1.7090093435985905],[2.1674352111458166,1.8163370426923022],[1.6814477787604538,0.14637281213572328],[2.2091336947122575,2.167089607178906],[2.168546709651868,1.59662470647375],[2.084542758680281,2.1307310977377982],[2.4970940338466985,2.423666409122853],[1.8940516719963534,3.117730813455209],[2.3590223391039116,2.287804871683037],[0.8729234519158415,2.0469636077102935],[1.4595681395797993,0.1331747589595762],[0.9116574011746669,2.1452913109950877],[2.600570847186176,2.9519280459659694],[1.8703453730394657,1.653163090902761],[1.7339306554555611,1.8665299199121108],[1.8808296321145452,0.4849774969938895],[0.9948993225427692,2.088652985169108],[1.2862384807988367,-0.07488874373440135],[1.6721143758987687,0.4197291140014009],[1.9916313107412298,1.2927664630337323],[2.0245838371271145,2.9287273503244395],[0.6591760860288799,2.412518533156826],[1.6068743938643189,0.061598879386761674],[1.5910397084552028,0.4372958426452872],[2.6302528020148177,1.963828425342869],[2.454901450274425,1.295732050875247],[2.0345917571156846,2.844665827452872],[1.4017238250783515,0.906818147298949],[1.5824203425838774,0.793092035490507],[2.197189216443839,2.9621449274823464],[1.9496027297181526,0.2597403067996996],[2.385597590708396,1.7094174983742132],[2.361125212666849,2.4191034184960336],[1.0553492652940704,1.8131538208786426],[1.6592270389425048,-0.02536890868400965],[1.5840011724492336,0.8055957238720047],[1.6455343558386955,0.7442166179896187],[1.6710429691029856,0.5762054709920643],[0.44437042592379616,2.136343878725933],[1.3648356607642542,1.9946064813089976],[0.8060099630570117,2.426558458276113],[2.1546644681435385,1.569637127117339],[2.6618818474869124,1.5912221676860276],[1.866627398967411,2.1515215669475354],[2.0414853383371687,1.5569952153608573],[1.9708656549266241,-0.14674247414773867],[1.4681916225381257,0.3285976868843885],[1.6790899768456715,1.9804477923833783],[1.311892961018714,0.06178387436676158],[1.8943444507494702,1.0980575634760077],[1.885170585856816,3.1753333961618906],[2.2374869069691457,0.8365911632292604],[2.789350063129156,1.972053529590466],[1.6386009521176037,0.6832621743985513],[0.6722173976215683,1.7951750957028008],[1.7857295794548378,0.7976907125590411],[1.8697466265833032,0.5009172394199],[1.527891252605619,1.7529506387641662],[1.7339861068763045,0.7807317799309327],[1.8700968369788993,1.9723944717252706],[2.2204548822251455,0.7815426502929468],[1.923303803351196,1.7642302281227633],[1.1941005734008985,0.5963357240269253],[1.7830538681007497,0.45356925045439533],[1.8891903030536872,-0.003638498549278668],[2.2446037057902735,1.778203768300488],[1.0872365966601647,2.0862078627519063],[2.4453516543786695,1.7894609168935016],[1.3583935746885938,2.1730758459745108],[1.631431569332104,0.5894403116050433],[2.1887945563967763,1.734311964496883],[1.5694351981699821,0.7010603555344774],[1.8256904030247627,1.8401790444532424],[0.5801119868146132,1.6427777876832712],[1.872421259794209,0.6444827318402016],[1.5167390568156085,-0.10140771595941256],[1.1964041313010594,2.0561777237303445],[2.081779584451899,1.9406030391395417],[1.1882741215291501,0.8305895419200633],[2.0436272423651185,1.7472596922713277],[0.8813014819464486,2.227253967697262],[0.6189882206676942,1.9940023449528477],[2.3063549082223527,2.9637716846292075],[1.6231892641179946,1.4443581552530236],[1.1682139107150176,0.772624923046768],[1.7966935981808065,0.7036597494562284],[1.4337004912793812,0.25519810482737726],[2.2622116003956263,0.791639248025187],[1.2812987633310982,0.9160244209572201],[2.2338715900815695,1.8744976705691485],[1.741999859624477,0.806704316835404],[2.2542140377569373,1.908416227637543],[1.0764886833393348,0.058930863744449224],[1.6062879206720282,0.49288883139468775],[1.7447393108953562,0.6115782859288287],[1.3581654467803834,0.5715950955923853],[2.2060548724081404,0.01024835816713665],[1.6228823524728924,-0.04088805968805387],[2.238693986966767,1.5677898355426896],[2.218148146888801,0.8473662817009915],[0.9481257826155816,1.6376376544569764],[1.7388672783011245,1.0177896736208698],[1.5596073125166727,2.399019677711488],[1.9511263689664777,2.163248699625498],[1.7562419321902045,0.0646070743863385],[1.79649722448286,0.3863336088700833],[1.4914762426510468,0.06816064554352663],[1.093028399364996,0.36560781464002434],[1.2694502939059535,1.9235504613068062],[2.2664606013848116,0.827883248544148],[2.070653517847485,1.480439374724841],[2.7630927930898084,2.111735015169666],[1.2675592793711576,0.7639594797437481],[2.447920806584426,1.516461388284133],[1.4256996813238576,0.2539565795391109],[2.747347019478367,1.9671066123147616],[1.854288725537841,0.49713771036826704],[1.1836501802075152,1.9251766145560447],[1.9803413773189322,2.140041752174557],[2.260197331562482,2.5793806255475693],[2.384178069178864,1.8039884904581072],[1.2466008617933135,0.8688664803375661],[2.5209850752845053,2.068198155465634],[1.8849452443149506,2.5366199286544187],[1.3726326810564744,2.5389922565533762],[0.5434839080248943,1.5213767124958486],[2.34083562827509,2.1088044899762393],[2.316900718357212,0.21929414036621908],[1.6820488543056373,0.17332432883056714],[1.8832522907131262,2.5162157131032106],[1.5132450534723771,1.9899523649099573],[2.0206114524697756,0.5819606880696476],[1.957050095284373,0.24661933985363327],[1.9683543253110916,2.7027783314932616],[1.63182362634611,1.4499735134546448],[1.9510512223940126,0.13610389935285128],[1.8138978076554009,1.0951429888586475],[1.95638941475511,1.8362601123534863],[2.5331308932453775,2.737480537401575],[0.6303014397814791,1.2664492036029618],[1.3348361668856996,0.6161182493201683],[2.297957666983083,2.0484498095851174],[2.4696440602333203,1.7700836058988214],[1.7284644327156076,2.191059469324788],[1.885149920764557,0.5056522005801684],[1.8694344179125018,0.5982346390989024],[0.44309884487796003,2.0567499604919206],[2.2921130768305122,3.1126122131831653],[2.1076037585095757,2.5004324001307685],[1.7464501043099872,0.3400454524188513],[1.7919498886465228,0.7060487907887658],[2.2270740424892987,0.5976049120590631],[1.6919309593846954,1.7103066032769152],[1.9716689181674867,2.150856863314223],[2.482700217320396,2.8398572676581013],[1.5246191909591937,0.48058689035600843],[1.0346080624814444,1.834894337850515],[2.0240344685158953,0.3665817885997348],[1.2941863251584582,0.31121884319602355],[1.6102120667572697,1.6278992444060407],[2.7504865655136705,1.564530509428856],[2.316951420083787,1.96582455802268],[1.3590623315811996,-0.15760166687604027],[0.6580115653991156,2.166665912460209],[1.8900986272008973,0.8672803122950503],[2.131807737577959,1.557916205774799],[1.0659389266956425,1.3048190317675885],[2.0332817233795444,1.6823458242926144],[1.2393976646016749,0.7012980690615085],[1.8495997067390135,0.011892070228743057],[1.317125403621192,1.4441944540577036],[2.2384160980920593,1.870196926196257],[1.0848530693363099,1.9915132631752184],[1.2153320500754146,2.145285885414267],[2.367730018988323,0.9695061192593809],[1.8487951366770974,3.042878500796726],[2.1232323929091876,2.3845256463242084],[1.5421636330279136,0.572644871692166],[1.1705394024276767,1.347458154634915],[2.720473266456705,3.0987777814314335],[2.279978753022285,2.7147972837645398],[1.9694485566609883,0.4643707085115669],[2.3562041528936715,1.7300190170002114],[1.0217197108498697,1.6448253383797418],[2.4803227290907954,2.6053771736889484],[1.5982870657464874,0.9348971646313247],[1.9307515257700367,0.3978560364528535],[0.9626029450673099,1.3355774012740096],[2.420040221701558,1.7005567175714187],[1.6394509881543033,1.4437537801060087],[2.5140949026184556,2.007481890974902],[1.7429440043847455,0.7377109233647725],[2.503961279212167,1.415000580471256],[2.1411030185260227,1.427941499902283],[1.7799194375861531,0.46377393243313436],[1.9280133697019544,1.3712364376018025],[1.5084533976704202,1.7964939500267754],[1.078927963054121,0.597302087380426],[2.013841592851652,2.766882162180429],[1.6373776499151655,1.4952889682997488],[2.190129453878352,1.7773859109635963],[0.712147257251009,2.179849626142894],[1.0129659124996584,2.3421484044198495],[1.5596524685024327,0.867956660320818],[0.8071648438131094,2.014774291505847],[2.5407272079888874,2.9491818626170088],[1.1829352476676847,0.3902534731686217],[2.1855700382311696,2.028899089259655],[2.7520762579236733,2.7034675825697914],[2.137124197930846,0.773204381823802],[0.9801113086321728,2.1561026938110968],[1.2789692540316968,0.013887323394141782],[1.7696625758189684,0.9055183580872304],[1.6842536690298833,0.4269687694895261],[1.0924025245000069,0.49055389216935863],[1.709153539868817,1.4133331022597666],[0.9396286045160527,2.612214086914707],[1.8909437376978513,0.5763008562764748],[2.319332022904561,0.6643439746320543],[1.908367832058217,0.6305003322662021],[1.765814482332337,1.6407941693899373],[2.024361465831127,1.8640106810975396],[2.4735865200069065,2.8101198875456532],[1.5807682289844087,-0.057849991161308845],[2.024437575624764,1.531128188162767],[2.041911253085739,2.2271901465264303],[2.1788638873203166,1.6998850135026775],[1.406803538193485,0.37338446581104756],[1.7236588623418152,2.1192393892309713],[1.9634947872420914,1.6813707093318424],[0.4407862103928266,1.2964184035620505],[2.3147093109804957,2.5392024059916762],[2.137222557192309,0.9432355781582441],[1.511457561220176,0.010395935531699929],[0.6558128158453274,2.0311123047927495],[2.4805355989643934,2.8716504604210114],[1.7956502297598607,0.21474063243606512],[1.8131119398899926,1.4927957843468587],[1.7355862150475037,2.044077341970759],[0.9759834063450514,2.1099671382048957],[2.1501309098467933,1.6124226221639257],[1.758596940265718,-0.04310717225360239],[1.8457973342096627,0.4178047332711642],[1.3752441995430817,0.6773564565531343],[2.249115761638931,2.019575602095144],[1.4502309526372748,0.9701453335828643],[1.6844745342427665,0.20013225626142805],[1.7517285515806829,0.037740760645845084],[0.7883483510892209,1.8488623260080528],[1.4759120725170467,0.8767345644039283],[2.579105079180999,1.3480976334541281],[2.4902207857219922,1.909972425806499],[1.9953808186109343,0.312101654390165],[2.4462052725777164,1.7728279829801399],[1.8815746371915691,0.618977041645097],[1.6539069165341915,0.7822592491264743],[2.379523990636562,2.848560294818364],[0.8076576222918678,1.3034542812931638],[2.4430336827998813,2.0975632649770093],[1.4383103908229309,0.10365316942629443],[1.0847105200342493,0.529785962171845],[1.7846832440880034,0.3840027431598486],[2.1541938553254094,3.0245574304547294],[2.6153000937891435,1.687028514983518],[1.814670004507233,0.07414904679974366],[2.5034484002904565,1.7811769553297352],[2.206286112704367,1.3099596794603705],[1.9289641877191452,0.005626005992172556],[2.149459434833759,2.1213136381257414],[2.001319082866103,1.5108573011202928],[1.731953639976827,0.7095648833104126],[0.9122526081973009,2.021470104818922],[2.3279484538741446,1.4167758248559383],[2.4941160156579127,2.405101452143848],[1.8195706981976656,1.605160230467158],[1.8424285954036457,2.7503191890761283],[2.0143868698820806,1.935544056549695],[1.7979828104297435,2.593375903722309],[2.1135748198482585,0.06683256353085854],[2.316738534531906,2.3631899445249838],[1.50175422883175,0.32631904570497006],[1.0868205218818487,0.5683708765325031],[1.899514414743234,0.26908273193922705],[1.4161736873680248,0.3703198947894326],[0.43723761766836855,1.2556152968928092],[2.2592464795838096,0.7811809469382561],[2.8744444827719033,2.0165522826057716],[1.3732712845279484,0.531846482851887],[2.1667583630286904,0.13868780548964],[0.8238706251753586,1.3365568879572451],[1.6199545442889716,0.13776484713357084],[1.325778328907803,2.6169828740832357],[2.4599214856554212,1.696394669333881],[2.4489203094201275,1.7481875379130192],[0.7278222493590009,1.547057328288758],[0.8682342746913645,1.7833157747798998],[0.9704219320757356,1.9495931768280146],[1.2049011064384687,2.6562220241740895],[2.330064665182056,1.8669606939289038],[2.490397217139769,2.0962952993545048],[1.9268593323547205,0.34892700316974345],[2.2222260973954824,1.9309481696608466],[2.4697737886126894,2.291685273403154],[0.9686004715681219,1.2798445398600835],[1.5000515530306768,1.2553896444948491],[1.2722211728111725,0.34072954780045595],[2.0316657213238423,0.527094103492938],[1.2348804668375395,0.3042719618868778],[1.8369471459121067,0.22424026953520015],[2.4114188722377365,2.0254524474612237],[1.9003171407222401,1.8039764786459052],[2.154934258940578,1.8729382755670527],[1.5449810708790785,1.4525815376237312],[1.5857089045596509,0.6814899214926976],[2.023855011056824,1.7325269271829926],[1.559137809842642,0.7166122259356417],[2.148188646085384,1.7526119337791872],[1.0978943896699525,0.5317673215769876],[1.0893262507989163,1.8677850503338531],[2.0094252537993476,2.10304606841631],[1.4989308580142358,2.1122045772235203],[1.7030271559284005,2.3429417535590855],[2.5488208630961338,1.6770440848341666],[1.9443726267154564,2.897683872716896],[1.1664704195053233,1.263430450622229],[0.7115250626665761,2.2507515737164936],[2.6683885767429976,2.8874884039270694],[1.0745749876804944,0.5398805693277151],[1.3713174984157066,0.062403762683728714],[2.3639615982280993,2.7311331815133175],[1.8510935558149177,0.2872463040654938],[2.2069176053698243,1.9689445673189887],[2.347814299363958,3.1618839324521497],[1.3711896218997928,1.180051000462457],[1.6012685469686343,0.07704073306124759],[2.0808587214321728,1.810094732003252],[2.2644140077853043,0.5407719841766486],[0.734675261447057,1.5148085152327737],[2.6915224538361016,2.3796191902085986],[1.8112256241888036,0.7707200456782837],[0.8135220190796321,1.9938285092585346],[0.5695513126349093,1.4364202182233],[2.2339069539644703,2.870608525786296],[1.6634242502597365,1.3314017942626075],[1.9193858642867414,0.48717668142308157],[1.466763439802461,0.9066976419778181],[1.9707636285153345,0.3261641543272299],[0.7342934673510984,1.553244815474376],[2.8056756594671355,2.1563507567747697],[1.7969406991514811,0.2949375865428442],[0.6469563303041066,1.6601606497529584],[0.8182045113606181,1.8105087496260017],[1.680231747130784,0.7874714631899379],[1.284105911104604,1.8004502449902806],[1.1351255844635677,1.2258540730356526],[1.7606053755923516,0.09538725799357506],[1.459954734564905,0.8196139945312635],[1.3650905218603389,1.6643630054768943],[1.2332499412545421,1.483296046528777],[1.4934304275842,0.6166903874180204],[1.9761657273981978,0.26470188724511245],[1.0437768321655507,2.732371722042411],[2.2235561379569173,1.3183763214492548],[1.4864588382901442,0.05007870381569046],[2.2862612497283346,1.3199240278360094],[1.1106183078098537,0.43765453165387247],[1.3606668379857816,0.5575986127896252],[0.8747159817902835,1.8235581360205564],[1.3474224006244895,1.3473167846892125],[1.2871227119167767,0.32927809012163245],[1.3863284585919362,0.26958580053081127],[2.8520133414960283,1.5279096672350265],[2.781776364792474,1.732108187302185],[2.136534085419614,0.21992210745620566],[1.4850845927400742,2.4130608255083015],[2.0625004858838776,2.2571689518579596],[0.8558468368649093,1.8730332300815684],[1.9228167308323443,2.0210152519668156],[1.3129530580495827,1.9216617430489784],[1.8049698888186367,0.7023245094084191],[1.9584533034127334,0.11049759881771903],[2.011324335543742,0.7700181241079882],[1.0838604810589552,1.3873572028341803],[1.9413272093118492,0.3028565913541754],[1.7107420813004972,0.27036044144717153],[2.4089105137710396,2.9062079042326423],[1.9005008445819662,2.1788803697160493],[2.5691372824813765,3.099946889255966],[2.2629354602990386,1.8693712313998658],[0.8356962593656513,2.3968755987813277],[1.861011317337021,0.6996666795129878],[1.6451951515523762,1.1730656185756034],[1.4415701631776048,1.8180046792551314],[1.6511481644726584,1.3276111078358144],[1.6502381508905892,2.1863139225456183],[1.0529924128256536,2.0379764281355475],[1.4256723416812476,0.6336972829953771],[2.361834393416504,1.582804814140839],[1.8238550726366236,0.09342509742937921],[1.622119779702122,0.5669676097864439],[1.228749208346323,0.09843878538106487],[1.2512745473104752,0.3069148030154455],[0.9426390781376579,1.7117443928049536],[1.9057567099078958,2.9423879746837223],[1.8798444121137474,-0.06841460691816459],[1.5393130002912363,0.05594452077715184],[1.6881966099140695,0.6930754888531835],[1.500361991510767,2.480725063411422],[1.8667378334852378,1.162611445515338],[2.2241096702833847,1.5821692243163112],[1.37146301255466,0.48444257682663194],[2.184618655615329,0.60349638226659],[2.1329370890894253,0.6775813371535803],[2.3978081369885595,1.6170045712409487],[2.0734037294369125,3.207633175522051],[1.8776100807545262,2.7371927692786944],[1.632329536995299,0.2865277916629395],[2.3117738278669733,1.9152347767058562],[1.1240614845704868,0.7736711056085868],[1.1279765661145884,2.6603561770629485],[2.694829954036763,2.6368951280158304],[2.19426830285681,0.548855334723546],[1.3888066617998271,0.36463401483941704],[1.8419197572827581,0.34506444161582084],[1.8652563463920369,0.3226857346516616],[1.193298392539203,1.9254501095570342],[2.310585407128523,3.1005481463779065],[2.690288391457142,1.8183565646813615],[1.9576231091823295,1.365246353273451],[1.239812643602392,1.2925685869392396],[1.7956716035154168,2.3305509926518035],[1.6187856157799205,0.4050299243622304],[1.867406399530835,2.751529450291862],[1.4241266485351265,1.7739313058298252],[2.485940185134009,3.090045838380891],[1.6750162106764748,2.10248069424671],[2.0783566450533737,0.07836920423601812],[2.2277011786651686,1.4215219171312852],[1.3600333135832674,2.3025229963012186],[1.1723952129681088,1.0032365272337698],[0.6107289343684683,2.401425425750043],[2.0609049045925945,2.2914300340945903],[2.1828220263932154,2.2829793739154893],[2.6067669097099575,2.1138192740660724],[1.843279209097183,1.7681465297526153],[0.8635572667145934,1.9546943240965302],[1.3337737912849157,1.9590591579383547],[2.5117487238284006,1.425966803688466],[1.6391866654580713,1.4621184503884552],[1.2734965333849066,0.49930128459340906],[2.27083262624947,0.04351318317273667],[1.1268847515138227,0.43432672131959904],[1.389874665386567,1.4510276180384942],[1.9114698128530703,0.46825783265302234],[1.9167344017646186,1.8810449696388245],[1.8338080422376986,0.9361421591642723],[1.1476376809785913,0.436106997774236],[2.002073708289387,1.8429571647973584],[1.5926069850805253,0.06906585878048721],[1.9124441820879325,0.12372521623207933],[2.4759846833784596,1.7057308843820942],[2.5319781461115407,2.5784596335228036],[2.1730495079765144,1.9067969322295673],[2.245637865022479,3.1150099396925532],[2.3465760120677936,1.598260594653944],[2.1260372913755616,2.3802283077300666],[2.2869595150140496,0.2222247916320652],[2.3079703917908128,1.966159457851021],[2.423817506465323,1.5200786885666147],[1.9688671859127056,1.7058706418393443],[1.9672069924017084,0.705456333849967],[1.8531387127322019,2.306148447163889],[2.0453067883141065,0.4218841436544355],[0.41679910346419835,1.7336533077356933],[2.198829826205153,0.6063357703533889],[1.9056738406958282,0.4333786989257684],[1.9205967679409666,2.20723265576135],[1.8216074792001573,0.021046791139438525],[1.8960195250087253,1.323120448044242],[2.341256765319064,2.7392369481527226],[1.7765492070950133,2.266234312644185],[1.398641079604403,0.8268489975402962],[1.7724220392392214,0.8768678960057518],[1.5888740355631683,1.683584957771168],[1.9760103743657784,3.080775673628148],[1.7683901271009939,1.4127847394831812],[2.4351824148229504,3.024521133722325],[1.8636361282472296,0.7739133282945092],[2.0809019919294074,2.793212345769829],[1.9256063420773106,2.712737479348024],[1.6597137887103426,1.4744448124901535],[1.5512091535480272,2.080769559153892],[2.388464178975277,0.874553892561644],[1.9789982637997703,1.8911816160522303],[1.9763265624976345,1.5777504412686039],[2.008743613042113,2.936435480101869],[1.7272273638214795,2.044248742923027],[0.7169540898605712,2.6926221362646166],[1.605340658678569,2.395690446705984],[1.5232240243585398,0.8073148320931897],[1.4089831106760378,0.007022481315656304],[2.198765899815834,0.6774100192810628],[2.674513566509635,2.4338703837668683],[2.3232345232291283,2.833717158477923],[2.0951209467143377,1.668003837455415],[2.7615010929678765,2.7694628858731685],[1.8431650353730915,0.47871720559154307],[1.1183437675097498,-0.057324471596909454],[1.9880692359009453,0.7536164077432173],[1.4090080222242456,2.1118174926980298],[1.0721917147865352,1.7738665126987687],[1.1184052161409515,0.2875633289691256],[2.2143037830734302,2.6405542984555774],[1.7465111530252382,0.37272053067639244],[1.5308146717011062,1.71424440881519],[0.8608059828762183,1.7383134566838532],[2.709997205887368,1.7926366096087984],[1.9922683901279366,2.023954169278389],[1.8281362358742466,0.6131131270735359],[1.5577622237389148,0.583134526267879],[0.4640158578502873,2.1143921370493794],[0.8595312150854356,1.7679419124423732],[1.7849073496761723,3.0270122544591564],[2.5844281259706605,1.8771787972028902],[0.7176138318614084,2.1259044205964557],[2.3298112900606833,2.0143538689013107],[1.8302397953649538,2.3096020854986783],[1.8215565183068705,0.6493038715012104],[2.6753029107247053,2.5300981761405814],[1.8323816760789366,1.9581444924365328],[1.5952826321415836,0.9279343144285693],[1.9150069845065225,0.7285154282924851],[2.390964175313261,1.5916793593274388],[1.5335255737521996,1.3194384896608577],[1.4806832858053514,2.508319802983334],[1.7318168013961213,0.729834542097813],[1.7099949369808543,0.3854058477461145],[1.4459347924134172,2.4386283726461104],[2.4282591293712623,2.158304050338111],[2.1623926915391736,1.8383402272700473],[2.1956715044121813,1.4681712545812113],[2.641536438942473,2.485967063061598],[2.4373008616518144,2.8490976266568353],[1.1165628031584667,1.0923427296938286],[1.729189987036792,0.8515306642120286],[1.8287538045609506,-0.08323866525476142],[1.1127842717863377,0.5323600825582245],[0.7016798047393356,1.3999323399625587],[1.3406397679952162,2.6570893933862125],[1.2922320612953693,0.17128128826087674],[2.3721524914420797,1.6428168023869536],[1.8088616278125396,2.3141443404823243],[0.6170014205218267,2.5024091473946832],[2.337502619198953,1.199220603055902],[2.4253527744883776,2.7699649630348313],[1.5097073683546038,0.18318703025377747],[1.2781456147102759,-0.09392925945378316],[0.8763444223567253,1.9887462123908977],[2.164213943538197,0.5482114396127127],[2.0427850950211144,0.01044815418691969],[1.8466956662270806,1.982350345284229],[2.753802062932545,1.394705151863048],[1.3930311755144875,1.7023307880286542],[2.4426046383958946,1.7991183270922848],[2.3994625192794534,1.801838773636098],[2.4327941780805964,1.1976386566008073],[0.7600667048974244,2.1112974085563456],[2.3471486321287385,2.8860053739602547],[1.9815522456080061,1.3736436464828334],[2.3052873065429793,0.2427109680661491],[1.4597310961332846,2.0262698281913267],[1.801979741899506,0.6283301393014054],[2.143079693825954,2.144540769562669],[2.029305382087705,0.7464763941806614],[1.6208487062218813,0.1370701179187256],[1.5018585728185174,2.130287545990958],[1.906666448894216,0.43960417194174095],[1.0565753437019398,0.4529769889574162],[2.6393772273518277,2.8770801615089256],[2.3295077747021864,0.6058287138211516],[1.946281740047124,1.9650905634873475],[1.9490879996347514,1.5142822335714978],[0.5442662654574728,1.5144279403072978],[1.5420591170021085,1.5357014413082226],[1.3610842380260961,0.6685797105834342],[2.0107901513640467,1.4924972781234724],[2.0467565657028963,2.019201980424297],[2.3926171507905667,2.230653954952605],[2.4699372496162524,1.7231568706685363],[1.8032023814556486,0.8452098864286545],[0.7450390092663952,2.1243228623799433],[1.63688854660291,0.543668603688065],[2.7492994101564423,2.765949166060854],[1.6056690867899244,0.013617615705194486],[2.0356841832222514,0.7534874241007751],[1.9664199671454095,1.8112235058850537],[1.6568134382271251,0.7669166222922754],[2.3779882243776163,1.6104868932377951],[1.8243641004445506,0.3883380942153839],[1.9596081582540474,1.1624603173067023],[2.6959238936978047,2.2217270724480525],[0.6769488774409292,2.6179267280858713],[1.7767155068842118,1.1860557346752993],[1.6807178160718,0.20716228410348791],[2.1867485691352972,1.869634768949373],[1.5911006594199508,1.0332751918321423],[1.3681896695605598,0.7134611349397303],[2.1130511711448863,0.9494484252295735],[2.3213456808376827,1.5915675545676233],[1.8058657376370806,-0.09330654686128426],[1.0968313799650793,2.0160865891628497],[2.1732512235769526,2.103055484022474],[2.6398021917576973,3.07445471151502],[1.5884877942007423,0.5577530969984706],[1.7691837597152027,0.49144689154466026],[0.9850788296391575,1.9851036782756244],[1.1266462787058469,1.9212016295168466],[1.313627485666107,0.5099883879905495],[1.4638427598570942,2.5791549787215695],[1.6517422585749282,0.4196009530666365],[1.2231359607238292,2.0977261510723095],[1.6913860564933891,0.4834367254648424],[1.4794491501709643,0.5468818444766351],[2.4333677904837323,1.4680794173004696],[2.4858602248674364,2.318667586498372],[2.1521571280178575,1.4947258022987728],[2.0756060107136207,1.8231568357444803],[1.4450151966828944,1.796512016578618],[1.2551420457700528,0.17356575275763053],[1.2489584209346276,0.7241387790493353],[2.179768646701276,1.8198920297042847],[1.5673054174036531,0.2325800221398041],[2.7494844186652667,2.050964642133316],[1.81458832186272,1.6256091621148387],[0.625327779907997,2.143496008139751],[1.8539085430801938,0.009990983101864304],[2.0974871990598736,1.8859792760730787],[2.52245126510715,1.9847606963538582],[2.1159936711954,1.8418590609559504],[1.9968025163008536,0.07420025160269939],[2.319791379865536,2.9410621476901886],[1.7386299509009104,0.2732303469095645],[1.9883087395544998,0.048007998318871814],[0.9890151064374003,1.5280079409952143],[2.2251808531626796,0.7509990199190303],[1.3408648228834852,1.377844965005973],[0.6084362103404972,1.6321789687231387],[1.7184648737987445,-0.0605489571619956],[1.870809600926278,3.1422131253772445],[2.7484186079146538,1.7425921329753236],[1.988407762451073,3.081464969434536],[2.5004076905516555,2.593709442126881],[2.0766484228758104,0.8952654634658717],[2.122330775248,1.3177546882955564],[0.6315079767897073,2.0986995957255346],[1.539408485279634,0.7496394924424044],[1.3986955830814125,1.4479281287333752],[0.9241176772601248,2.329070493139077],[2.6596936985108592,2.233496924720869],[1.947702931267965,0.9669571269235746],[2.3969057462556416,2.2730422422076817],[1.811878935438701,1.5647747477528058],[1.373562064609585,2.288859627619144],[2.053932623157748,1.9097059748666265],[0.8844328654676519,1.9071406769241948],[1.6654846629403686,0.6200889945630063],[2.3528133404684732,2.1262110463461825],[2.2188127237088797,2.235550442671235],[1.355509542988603,0.26937441997415645],[1.9327642747364235,2.8258673159593624],[1.3853230475312435,0.32622199121435147],[2.0510629987832707,1.2837867969112011],[1.4718273795689456,0.7207667538861015],[0.8046302342807913,1.9353634152881898],[2.2378707097977717,0.0669346635531064],[2.473855747051711,1.8801837803090469],[0.8039444581818483,1.5867046760992516],[1.7380285190456695,1.7089731479775792],[2.2542604813127802,2.2465740647737134],[2.5700203320974415,2.105862137111424],[2.529257777673324,3.043650052039963],[2.0028147149133315,0.08562931266513307],[1.993214220461893,0.5463719840992762],[0.6945597721271616,1.866203743235701],[2.4739715854570843,3.0999736840567165],[0.5960001233119926,1.980891474664696],[1.602760778833741,1.795721997416427],[1.5654535802432048,2.0751854057554997],[1.7092978391169114,1.846584242019224],[2.008197157930854,0.5714722712308952],[2.7064902084578577,2.8831518674151306],[1.8840873022626887,1.0395077592010655],[2.167284630914966,-0.11687358623664768],[1.9995463870976415,2.101971826244433],[1.536
gitextract_bwhds1og/
├── .gitignore
├── Pharo4.0/
│ └── KMeans.st
├── README.md
├── c/
│ ├── compile.sh
│ ├── hashmap.c
│ ├── hashmap.h
│ ├── kmeans.c
│ ├── kmeans.h
│ ├── main.c
│ ├── point.c
│ └── point.h
├── chapel/
│ ├── .gitignore
│ ├── Makefile
│ └── main.chpl
├── clojure/
│ ├── project.clj
│ └── src/
│ └── clj/
│ └── kmeans/
│ ├── algo.clj
│ └── benchmark.clj
├── cpp/
│ ├── .gitignore
│ ├── Point.cpp
│ ├── Point.h
│ ├── benchmark.cpp
│ ├── biicode.conf
│ ├── kmeans.cpp
│ └── kmeans.h
├── crystal/
│ ├── .gitignore
│ └── kmeans.cr
├── cuda/
│ ├── CMakeLists.txt
│ └── src/
│ ├── config.h
│ ├── kmeans.cu
│ ├── kmeans.h
│ ├── main.cu
│ ├── point.cu
│ └── point.h
├── d/
│ └── main.d
├── elixir/
│ ├── kmeans.ex
│ └── main.exs
├── erlang/
│ ├── kmeans.erl
│ └── main.erl
├── factor/
│ └── kmeans/
│ ├── benchmark/
│ │ └── benchmark.factor
│ └── kmeans.factor
├── fsharp/
│ ├── .gitignore
│ ├── Makefile
│ ├── kmeans.fs
│ ├── main.fs
│ └── paket.dependencies
├── go/
│ ├── .gitignore
│ └── main.go
├── haskell/
│ ├── Kmeans.hs
│ ├── Main.hs
│ ├── Point.hs
│ ├── Setup.hs
│ └── kmeans.cabal
├── java/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ ├── Entry.java
│ ├── KMeans.java
│ └── Point.java
├── java8/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── example/
│ ├── KMeans.java
│ ├── Main.java
│ └── Point.java
├── julia/
│ └── kmeans.jl
├── kotlin/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── kmeans.kt
├── lisp/
│ ├── kmeans.lisp
│ └── readme.txt
├── lua/
│ └── kmeans.lua
├── nim/
│ ├── algo.nim
│ └── benchmark.nim
├── node/
│ ├── kmeans.js
│ └── package.json
├── ocaml/
│ ├── kmeans.ml
│ ├── kmeans.mli
│ ├── main.ml
│ └── point.ml
├── opencl/
│ ├── .gitignore
│ ├── kmeans.cl
│ ├── kmeans.nim
│ ├── kmeans.nimble
│ ├── point.h
│ ├── point.nim
│ └── util.nim
├── openmp/
│ ├── compile.sh
│ ├── makefile
│ └── src/
│ ├── config.h
│ ├── kmeans.c
│ ├── kmeans.h
│ ├── main.c
│ ├── point.c
│ └── point.h
├── parasail/
│ ├── benchmark.psl
│ ├── kmeans.psl
│ └── point.psl
├── perl/
│ └── kmeans.pl
├── pharo3/
│ └── KMeans.st
├── points.json
├── pony/
│ ├── .gitignore
│ ├── Makefile
│ └── kmeans/
│ └── main.pony
├── python/
│ └── kmeans.py
├── results
├── ruby/
│ └── kmeans.rb
├── rust/
│ ├── .gitignore
│ ├── Cargo.toml
│ └── src/
│ ├── algo.rs
│ ├── lib.rs
│ ├── main.rs
│ └── point.rs
├── scala/
│ ├── build.sbt
│ └── src/
│ └── main/
│ └── scala/
│ └── kmeans/
│ ├── Algo.scala
│ └── Main.scala
├── scala-js/
│ ├── .gitignore
│ ├── build.sbt
│ ├── project/
│ │ ├── build.properties
│ │ └── plugins.sbt
│ └── src/
│ └── main/
│ └── scala/
│ └── kmeans/
│ ├── Algo.scala
│ └── Main.scala
├── scala-native/
│ ├── build.sbt
│ ├── project/
│ │ ├── build.properties
│ │ └── plugins.sbt
│ └── src/
│ └── main/
│ └── scala/
│ └── kmeans/
│ ├── Algo.scala
│ ├── Main.scala
│ └── native.scala
├── stanza/
│ ├── compile.sh
│ ├── kmeans.stanza
│ └── kmeansutils.c
├── swift/
│ ├── .gitignore
│ ├── kmeans.swift
│ └── main.swift
└── x10/
├── CJson.x10
├── KMeans.x10
├── Main.x10
├── Makefile
├── RichPoint.x10
├── javalib/
│ └── jackson-core-2.5.1.jar
├── jsonRead.cc
├── jsonRead.h
└── jsonRead.java
SYMBOL INDEX (178 symbols across 34 files)
FILE: c/hashmap.c
function insert (line 9) | void insert(Point* pkey, Point* pelem)
function iterator (line 32) | void iterator(gpointer key, gpointer value, gpointer ret) {
function setCluster (line 37) | void setCluster(Clusters* ret) {
FILE: c/kmeans.c
function dist (line 12) | double dist(Point* p1, Point* p2)
function average (line 20) | void average(PointArray* xs, Point* ret)
function closest (line 33) | long closest(Point* p, PointArray* choices)
function calcClusters (line 49) | void calcClusters(PointArray* xs, Clusters* clusters, PointArray* centro...
function run (line 66) | void run(PointArray* xs, Clusters* clusters)
FILE: c/kmeans.h
type PointArray (line 6) | typedef struct {
type Clusters (line 11) | typedef struct {
FILE: c/main.c
function getTime (line 13) | long int getTime(PointArray* xs, Clusters* clusters) {
function main (line 26) | int main()
FILE: c/point.c
function divide (line 7) | void divide(Point* p, long d)
function add (line 14) | void add(Point* p1, Point* p2)
function sub (line 21) | void sub(Point* p1, Point* p2)
function sq (line 28) | double sq(double x)
function modulus (line 33) | double modulus(Point* p)
FILE: c/point.h
type Point (line 4) | typedef struct {
FILE: cpp/Point.cpp
function Point (line 20) | Point Point::operator+(const Point& q) const {
function Point (line 24) | Point Point::operator-(const Point& q) const {
function Point (line 28) | Point Point::operator/(double k) const {
function dist (line 44) | double dist(const Point& p, const Point& q) {
function ostream (line 48) | ostream& operator<<(ostream& os, const Point& p) {
FILE: cpp/Point.h
function norm (line 14) | double norm() const;
FILE: cpp/benchmark.cpp
function Point (line 22) | Point read_point(const Json& json) {
function read_points (line 30) | vector<Point> read_points(const string& path) {
function main (line 45) | int main() {
FILE: cpp/kmeans.cpp
function Point (line 10) | Point average(const vector<Point>& v) {
function Point (line 14) | Point closest(Point p, const vector<Point>& centroids) {
function group_by (line 28) | unordered_map<Point, vector<Point>> group_by(const vector<Point>& points...
function update_centroids (line 37) | void update_centroids(const vector<Point>& points, vector<Point>& centro...
function kmeans (line 46) | vector<Point> kmeans(const vector<Point>& points, int n, int iterations) {
FILE: cuda/src/point.h
type Point (line 4) | typedef struct {
type Centroid (line 11) | typedef struct {
FILE: elixir/kmeans.ex
class Kmeans (line 1) | defmodule Kmeans
method sq (line 3) | defp sq(x) do
method distance (line 7) | defp distance({x1, y1}, {x2, y2}) do
method closest (line 11) | defp closest(point, centroids) do
method clusters (line 15) | defp clusters(centroids, points) do
method sum (line 19) | defp sum({x1, y1}, {x2, y2}) do
method shrink (line 23) | defp shrink({x, y}, factor) do
method average (line 27) | defp average(cluster) do
method step (line 31) | defp step(points, iterations, centroids) do
method run (line 38) | def run(points, k, iterations) do
FILE: elixir/main.exs
class Main (line 1) | defmodule Main
method strip_brackets (line 3) | defp strip_brackets(xs) do
method parse_float (line 7) | defp parse_float(xs) do
method to_tuples (line 11) | defp to_tuples(xs) do
method read_points (line 18) | defp read_points(filename) do
method main (line 26) | def main() do
FILE: go/main.go
function sq (line 12) | func sq(x float64) float64 {
type Point (line 16) | type Point struct
method add (line 20) | func (p Point) add(p2 Point) Point {
method sub (line 23) | func (p Point) sub(p2 Point) Point {
method divide (line 26) | func (p Point) divide(d float64) Point {
method modulus (line 29) | func (p Point) modulus() float64 {
function dist (line 33) | func dist(p1 Point, p2 Point) float64 {
function average (line 37) | func average(points []Point) Point {
function closest (line 46) | func closest(p Point, choices []Point) int {
function clusters (line 59) | func clusters(xs []Point, centroids []Point) [][]Point {
function run (line 76) | func run(n int, iters int, xs []Point) [][]Point {
function main (line 96) | func main() {
FILE: java/src/main/java/Entry.java
class Entry (line 7) | public class Entry {
method main (line 11) | public static void main(String[] args) throws Exception {
method executionTime (line 50) | private static void executionTime(KMeans kmeans) {
FILE: java/src/main/java/KMeans.java
class KMeans (line 7) | public class KMeans {
method KMeans (line 15) | public KMeans(Point[] Xs, int n, int iters) {
method KMeans (line 21) | public KMeans(Point[] Xs) {
method dist (line 25) | private double dist(Point p1, Point p2) {
method average (line 29) | private Point average(ArrayList<Point> xs) {
method closest (line 40) | private Point closest(Point x, Point[] choices) {
method clusters (line 53) | private Collection<ArrayList<Point>> clusters() {
method run (line 66) | public Collection<ArrayList<Point>> run() {
FILE: java/src/main/java/Point.java
class Point (line 2) | public class Point {
method Point (line 6) | public Point(double x, double y) {
method divide (line 11) | public Point divide(double d) {
method divideToThis (line 15) | public void divideToThis(double d) {
method add (line 21) | public Point add(Point p2) {
method addToThis (line 25) | public void addToThis(Point p2) {
method sub (line 31) | public Point sub(Point p2) {
method sq (line 35) | private double sq(double x) {
method modulus (line 39) | public double modulus() {
method toString (line 43) | @Override public String toString() {
FILE: java8/src/main/java/com/example/KMeans.java
class KMeans (line 14) | public class KMeans {
method run (line 19) | public void run(List<Point> xs) {
method clusters (line 29) | public Collection<List<Point>> clusters(List<Point> xs, List<Point> ce...
method closest (line 33) | public Point closest(final Point x, List<Point> choices) {
method sq (line 38) | public double sq(double x) { return x*x; }
method dist (line 40) | public double dist(Point x, Point y) { return x.minus(y).getModulus(); }
method average (line 42) | public Point average(List<Point> xs) {
FILE: java8/src/main/java/com/example/Main.java
class Main (line 17) | public class Main {
method readPoints (line 19) | private List<Point> readPoints(String path) throws Exception {
method main (line 26) | public void main() throws Exception {
method main (line 40) | public static void main(String[] args) throws Exception {
FILE: java8/src/main/java/com/example/Point.java
class Point (line 6) | class Point {
method Point (line 9) | public Point(double x, double y) {
method getX (line 13) | public double getX() {
method getY (line 17) | public double getY() {
method plus (line 21) | public Point plus(Point p2) {
method minus (line 24) | public Point minus(Point p2) {
method div (line 27) | public Point div(double d) {
method getModulus (line 30) | public Double getModulus() { return Math.sqrt(sq(x) + sq(y)); }
method sq (line 31) | private double sq(double x) { return x*x; }
method toString (line 33) | @Override
FILE: node/kmeans.js
function sq (line 4) | function sq(x) { return x * x }
function dist (line 6) | function dist(x, y) {
function closest (line 10) | function closest(x, choices) {
function clusters (line 14) | function clusters(xs, centroids) {
function vsum (line 21) | function vsum(v, w) {
function average (line 25) | function average(xs) {
function run (line 32) | function run(xs, n, iters) {
FILE: opencl/point.h
type Point (line 1) | typedef struct {
type Centroid (line 7) | typedef struct {
type Accum (line 12) | typedef struct {
FILE: openmp/src/kmeans.c
function group_by_cluster (line 10) | void group_by_cluster(Point* points, Centroid* centroids)
function sum_points_cluster (line 34) | void sum_points_cluster(Point* points, Centroid* centroids)
function update_centroids (line 50) | void update_centroids(Centroid* centroids)
function clear_last_iteration (line 62) | void clear_last_iteration(Centroid* centroids)
function km_execute (line 78) | void km_execute(Point* points, Centroid* centroids)
FILE: openmp/src/main.c
function print_me (line 18) | void print_me(Centroid* centroids)
function run_kmeans (line 36) | long int run_kmeans(Point* points, Centroid* centroids)
function main (line 78) | int main(int argc, char *argv[])
FILE: openmp/src/point.c
function divide (line 7) | void divide(Point* p, long d)
function add (line 14) | void add(Point* p1, Point* p2)
function sub (line 21) | void sub(Point* p1, Point* p2)
function sq (line 28) | double sq(double x)
function modulus (line 33) | double modulus(Point* p)
function km_distance (line 38) | double km_distance(Point* p, Centroid* c)
FILE: openmp/src/point.h
type Point (line 4) | typedef struct {
type Centroid (line 10) | typedef struct {
FILE: python/kmeans.py
class Point (line 7) | class Point(object):
method __init__ (line 10) | def __init__(self, x,y):
method x (line 13) | def x(self):
method y (line 15) | def y(self):
method __add__ (line 17) | def __add__(self,other):
method __div__ (line 19) | def __div__(self,value):
method dist (line 21) | def dist(self,other):
method closest (line 23) | def closest(self,points):
method __repr__ (line 25) | def __repr__(self):
function update_centroids (line 28) | def update_centroids(points,centroids):
function groupby (line 35) | def groupby(points,centroids):
function run (line 42) | def run(xs, n, iters=15):
FILE: ruby/kmeans.rb
class Point (line 3) | class Point
method initialize (line 7) | def initialize(x, y)
method + (line 12) | def +(other)
method / (line 16) | def /(value)
method dist (line 20) | def dist(other)
method closest (line 24) | def closest(points)
method inspect (line 30) | def inspect
function update_centroids (line 35) | def update_centroids(points, centroids)
function groupby (line 44) | def groupby(points, centroids)
function run (line 53) | def run(xs, n, iters=15)
FILE: rust/src/algo.rs
function dist (line 6) | fn dist(v: Point, w: Point) -> f64 {
function avg (line 10) | fn avg(points: &[Point]) -> Point {
function closest (line 17) | fn closest(x: Point, ys: &[Point]) -> Point {
function clusters (line 28) | fn clusters(xs: &[Point], centroids: &[Point]) -> Vec<Vec<Point>> {
function run (line 50) | pub fn run(points: &[Point], n: u32, iters: u32) -> Vec<Vec<Point>> {
FILE: rust/src/main.rs
function benchmark (line 15) | fn benchmark(points: &[Point], times: i32) -> f64 {
function main (line 27) | fn main() {
FILE: rust/src/point.rs
type Point (line 9) | pub struct Point(pub f64, pub f64);
method norm (line 16) | pub fn norm(self: &Point) -> f64 {
function sq (line 11) | fn sq(x: f64) -> f64 {
method hash (line 22) | fn hash<H: Hasher>(&self, state: &mut H) {
type Output (line 34) | type Output = Point;
method add (line 36) | fn add(self, other: Point) -> Point {
type Output (line 42) | type Output = Point;
method sub (line 44) | fn sub(self, other: Point) -> Point {
FILE: stanza/kmeansutils.c
function getTime (line 8) | long int getTime() {
function loadFile (line 17) | int loadFile() {
function xValueAt (line 28) | double xValueAt(int i) {
function yValueAt (line 34) | double yValueAt(int i) {
FILE: x10/jsonRead.cc
function parse (line 10) | void parse() {
function nextX (line 26) | double nextX() {
function nextY (line 30) | double nextY() {
FILE: x10/jsonRead.java
class jsonRead (line 2) | public class jsonRead {
method initialize (line 10) | public static void initialize() {
method getNextX (line 44) | public static double getNextX() {
method getNextY (line 48) | public static double getNextY() {
Condensed preview — 137 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,126K chars).
[
{
"path": ".gitignore",
"chars": 747,
"preview": "cuda/build/*\ncuda/.metadata\ncuda/RemoteSystemsTempFiles\ncuda/kmeans.out*\ncuda/CMakeCache.txt\ncuda/CMakeFiles/\ncuda/Makef"
},
{
"path": "Pharo4.0/KMeans.st",
"chars": 3118,
"preview": "Object subclass: #KMeans\r\tinstanceVariableNames: 'iterations clusters'\r\tclassVariableNames: ''\r\tpoolDictionaries: ''\r\tca"
},
{
"path": "README.md",
"chars": 6787,
"preview": "This benchmark is born to compare the performance of Pharo 3 in executing a simple machine learning algorithm with a ref"
},
{
"path": "c/compile.sh",
"chars": 285,
"preview": "gcc -Wall -O3 -c hashmap.c -o hashmap.o `pkg-config --cflags --libs glib-2.0`\ngcc -Wall -O3 -c kmeans.c -o kmeans.o\ngcc "
},
{
"path": "c/hashmap.c",
"chars": 986,
"preview": "#include <stdlib.h>\n#include <stdio.h>\n#include\"hashmap.h\"\n#include<string.h>\n#include <glib.h>\n\nGHashTable* hash = NULL"
},
{
"path": "c/hashmap.h",
"chars": 216,
"preview": "#ifndef HASHMAP_H_INCLUDED\n#define HASHMAP_H_INCLUDED\n\n#include\"point.h\"\n#include\"kmeans.h\"\n\nvoid insert(Point* key, Poi"
},
{
"path": "c/kmeans.c",
"chars": 1992,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include\"kmeans.h\"\n#include\"point.h\"\n#include\"hashmap.h\"\n\nint n = 10;\nint iters ="
},
{
"path": "c/kmeans.h",
"chars": 292,
"preview": "#ifndef KMEANS_H_INCLUDED\n#define KMEANS_H_INCLUDED\n\n#include\"point.h\"\n\ntypedef struct {\n long size;\n Point points"
},
{
"path": "c/main.c",
"chars": 1353,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n\n#include\"point.h\"\n#include\"hashmap.h\"\n\n#include <string.h>\n#include <jansson.h>\n"
},
{
"path": "c/point.c",
"chars": 484,
"preview": "#include<math.h>\n#include\"point.h\"\n\n#include <stdlib.h>\n#include <stdio.h>\n\nvoid divide(Point* p, long d)\n{\n p->x = p"
},
{
"path": "c/point.h",
"chars": 280,
"preview": "#ifndef POINT_H_INCLUDED\n#define POINT_H_INCLUDED\n\ntypedef struct {\n double x;\n double y;\n} Point;\n\nvoid divide(Po"
},
{
"path": "chapel/.gitignore",
"chars": 7,
"preview": "kmeans\n"
},
{
"path": "chapel/Makefile",
"chars": 309,
"preview": "MAKEFLAGS = --no-print-directory\n\nCHPL = chpl\n\nTARGETS = \\\n\ndefault: all\n\nclean: FORCE\n\trm -f kmeans\n\nall:\n\t$(CHPL) --fa"
},
{
"path": "chapel/main.chpl",
"chars": 3357,
"preview": "const n: int = 10;\nconst iters: int = 15;\n\nconst executions: int = 100;\n\nclass point {\n\tvar x: real;\n\tvar y: real;\n\n\tpro"
},
{
"path": "clojure/project.clj",
"chars": 194,
"preview": "(defproject kmeans \"0.1.0\"\n :description \"Kmeans benchmark\"\n\n :dependencies [\n [org.clojure/clojure \"1.7.0\"]\n [c"
},
{
"path": "clojure/src/clj/kmeans/algo.clj",
"chars": 706,
"preview": "(ns kmeans.algo)\n\n(defn sq [x] (* x x))\n\n(defn v- [[a b] [c d]]\n [(- a c) (- b d)])\n\n(defn v+ [[a b] [c d]]\n [(+ a c) "
},
{
"path": "clojure/src/clj/kmeans/benchmark.clj",
"chars": 575,
"preview": "(ns kmeans.benchmark\n (:require\n [clojure.java.io :as io]\n [cheshire.core :as json])\n (:use [kmeans.algo]))\n\n(de"
},
{
"path": "cpp/.gitignore",
"chars": 9,
"preview": "/bii\n/bin"
},
{
"path": "cpp/Point.cpp",
"chars": 870,
"preview": "#include <math.h>\n#include \"Point.h\"\n\nusing std::cout;\nusing std::ostream;\nusing std::hash;\nusing std::size_t;\n\nPoint::P"
},
{
"path": "cpp/Point.h",
"chars": 686,
"preview": "#ifndef GUARD_Point\n#define GUARD_Point\n\n#include <iostream>\n\nclass Point {\n public:\n double x, y;\n Point();\n "
},
{
"path": "cpp/benchmark.cpp",
"chars": 1568,
"preview": "#include <string>\n#include <algorithm>\n#include <fstream>\n#include <iostream>\n#include <iomanip>\n#include <vector>\n#incl"
},
{
"path": "cpp/biicode.conf",
"chars": 1634,
"preview": "# Biicode configuration file\n\n[requirements]\n\t lasote/json11: 4\n\n[parent]\n # The parent version of this block. Must m"
},
{
"path": "cpp/kmeans.cpp",
"chars": 1268,
"preview": "#include <numeric>\n#include <limits>\n#include <unordered_map>\n#include <vector>\n#include \"kmeans.h\"\n\nusing std::vector;\n"
},
{
"path": "cpp/kmeans.h",
"chars": 172,
"preview": "#ifndef GUARD_Kmeans\n#define GUARD_Kmeans\n\n#include <vector>\n#include \"Point.h\"\n\nstd::vector<Point> kmeans(const std::ve"
},
{
"path": "crystal/.gitignore",
"chars": 7,
"preview": "/kmeans"
},
{
"path": "crystal/kmeans.cr",
"chars": 1292,
"preview": "require \"json\"\n\nN = 10\nITERS = 15\n\nstruct Point\n getter x, y\n\n def initialize(@x : Float64, @y : Float64)\n end\n\n "
},
{
"path": "cuda/CMakeLists.txt",
"chars": 439,
"preview": "# CMakeLists.txt for G4CU project "
},
{
"path": "cuda/src/config.h",
"chars": 578,
"preview": "#ifndef CONFIGURATION_H_INCLUIDED\n#define CONFIGURATION_H_INCLUIDED\n\n// set to 1 if you want run repository specificatio"
},
{
"path": "cuda/src/kmeans.cu",
"chars": 6468,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n\n#include \"kmeans.h\"\n#include \"point.h\"\n#include \"config.h\"\n\n/**\n Groups the p"
},
{
"path": "cuda/src/kmeans.h",
"chars": 804,
"preview": "#ifndef KMEANS_H_INCLUDED\n#define KMEANS_H_INCLUDED\n\n#include \"point.h\"\n\n__global__ void km_group_by_cluster(Point* poin"
},
{
"path": "cuda/src/main.cu",
"chars": 3908,
"preview": "#include <sys/types.h>\n#include <math.h>\n#include <errno.h>\n\n#include <stdio.h>\n#include <stdlib.h>\n\n#include <string.h>"
},
{
"path": "cuda/src/point.cu",
"chars": 738,
"preview": "#include\"point.h\"\n\n#include <stdlib.h>\n#include <stdio.h>\n\n__device__ void km_divide(Point* p, long d) {\n p->x = p->x"
},
{
"path": "cuda/src/point.h",
"chars": 527,
"preview": "#ifndef POINT_H_INCLUDED\n#define POINT_H_INCLUDED\n\ntypedef struct {\n float x;\n float y;\n int cluster;\n} Point;\n"
},
{
"path": "d/main.d",
"chars": 2295,
"preview": "import std.stdio;\nimport std.math;\nimport std.json;\nimport std.file;\nimport std.datetime;\n\nclass Point\n{\n\tconst double x"
},
{
"path": "elixir/kmeans.ex",
"chars": 924,
"preview": "defmodule Kmeans do\n\n defp sq(x) do\n x * x\n end\n\n defp distance({x1, y1}, {x2, y2}) do\n :math.sqrt( sq(x1 - x2)"
},
{
"path": "elixir/main.exs",
"chars": 899,
"preview": "defmodule Main do\n\n defp strip_brackets(xs) do\n Enum.slice xs, 1, length(xs) - 2\n end\n\n defp parse_float(xs) do\n "
},
{
"path": "erlang/kmeans.erl",
"chars": 1177,
"preview": "-module(kmeans).\n-export([run/3]).\n-compile(inline).\n\nrun(Xs, N, Iters) ->\n InitCentroids = lists:sublist(Xs, N),\n "
},
{
"path": "erlang/main.erl",
"chars": 576,
"preview": "-module(main).\n-export([run/0]).\n\ntimes() -> 100.\n\nn() -> 10.\niters() -> 15.\n\nrun() ->\n\tXs = read_points(\"../points.json"
},
{
"path": "factor/kmeans/benchmark/benchmark.factor",
"chars": 281,
"preview": "USING: generalizations io.encodings.utf8 io.files json.reader kernel kmeans tools.time ;\nIN: kmeans.benchmark\n\n: load-po"
},
{
"path": "factor/kmeans/kmeans.factor",
"chars": 586,
"preview": "USING: assocs generalizations kernel math.statistics math.vectors sequences ;\nIN: kmeans\n\n: closest ( ys x -- y ) [ dist"
},
{
"path": "fsharp/.gitignore",
"chars": 79,
"preview": "*.exe\npaket.lock\n.paket/paket.exe\npackages\n*.dll\n!.paket/paket.bootstrapper.exe"
},
{
"path": "fsharp/Makefile",
"chars": 269,
"preview": "\ndefault: all\n\nall: \n\tmono .paket/paket.bootstrapper.exe\n\tmono .paket/paket.exe install\n\tcp packages/Newtonsoft.Json/lib"
},
{
"path": "fsharp/kmeans.fs",
"chars": 1289,
"preview": "module Kmeans\n\ntype Point = { x: double; y: double }\n\nlet sq (x: double) = x*x\n\ntype Point with\n static member (+) (p1:"
},
{
"path": "fsharp/main.fs",
"chars": 607,
"preview": "open Kmeans\nopen System.IO\nopen FSharp.Data\nopen Newtonsoft.Json\nopen Newtonsoft.Json.Linq\n\nlet file = File.ReadAllText("
},
{
"path": "fsharp/paket.dependencies",
"chars": 55,
"preview": "source https://nuget.org/api/v2\n\nnuget Newtonsoft.Json\n"
},
{
"path": "go/.gitignore",
"chars": 5,
"preview": "main\n"
},
{
"path": "go/main.go",
"chars": 2204,
"preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"math\"\n\t\"time\"\n)\n\n\nfunc sq(x float64) float64 {\n\treturn x *"
},
{
"path": "haskell/Kmeans.hs",
"chars": 794,
"preview": "module Kmeans where\nimport Data.List (minimumBy)\nimport Data.Ord (comparing)\nimport Data.Map (Map, fromListWith, elems)\n"
},
{
"path": "haskell/Main.hs",
"chars": 773,
"preview": "module Main where\nimport Text.JSON (decode, Result(..))\nimport Text.Printf (printf)\nimport System.CPUTime (getCPUTime)\ni"
},
{
"path": "haskell/Point.hs",
"chars": 852,
"preview": "module Point where\nimport GHC.Float (int2Double)\nimport Control.DeepSeq (NFData)\n\ndata Point = Point Double Double deriv"
},
{
"path": "haskell/Setup.hs",
"chars": 46,
"preview": "import Distribution.Simple\nmain = defaultMain\n"
},
{
"path": "haskell/kmeans.cabal",
"chars": 681,
"preview": "-- Initial kmeans.cabal generated by cabal init. For further\n-- documentation, see http://haskell.org/cabal/users-guide"
},
{
"path": "java/pom.xml",
"chars": 1207,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
},
{
"path": "java/src/main/java/Entry.java",
"chars": 1298,
"preview": "import java.io.File;\n\nimport com.fasterxml.jackson.core.JsonFactory;\nimport com.fasterxml.jackson.core.JsonParser;\nimpor"
},
{
"path": "java/src/main/java/KMeans.java",
"chars": 1715,
"preview": "\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Iterator;\n\npublic c"
},
{
"path": "java/src/main/java/Point.java",
"chars": 682,
"preview": "\npublic class Point {\n\tdouble x = 0;\n\tdouble y = 0;\n\n\tpublic Point(double x, double y) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t}\n"
},
{
"path": "java8/pom.xml",
"chars": 1449,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n xmlns:xsi=\"http://www"
},
{
"path": "java8/src/main/java/com/example/KMeans.java",
"chars": 1333,
"preview": "package com.example;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport st"
},
{
"path": "java8/src/main/java/com/example/Main.java",
"chars": 1505,
"preview": "package com.example;\n\nimport com.fasterxml.jackson.core.JsonFactory;\nimport com.fasterxml.jackson.core.JsonParser;\nimpor"
},
{
"path": "java8/src/main/java/com/example/Point.java",
"chars": 749,
"preview": "package com.example;\n\n/**\n * Created by evacchi on 28/02/15.\n */\nclass Point {\n double x,y;\n\n public Point(double "
},
{
"path": "julia/kmeans.jl",
"chars": 1387,
"preview": "# do Pkg.add(\"JSON\") first\nimport Base.+\nimport Base./\n\nusing JSON\n\ntype Point\n x::Float64\n y::Float64\nend\n\n+(p1::"
},
{
"path": "kotlin/pom.xml",
"chars": 3348,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n xmlns:xsi=\"http://www"
},
{
"path": "kotlin/src/main/java/kmeans.kt",
"chars": 3058,
"preview": "import java.io.File\nimport com.fasterxml.jackson.core.type.TypeReference\nimport com.fasterxml.jackson.databind.ObjectMap"
},
{
"path": "lisp/kmeans.lisp",
"chars": 4157,
"preview": "(declaim (optimize (speed 3) (space 0) (debug 0) (safety 0) (compilation-speed 0)))\r\n\r\n(defconstant n 10)\r\n(defconstant "
},
{
"path": "lisp/readme.txt",
"chars": 417,
"preview": "This is fairly straightforward, portable Common Lisp code. No additional libraries are necessary.\nThe code has been test"
},
{
"path": "lua/kmeans.lua",
"chars": 2138,
"preview": "local sqrt = math.sqrt\nlocal clock = os.clock\nlocal json = require(\"dkjson\")\n\nlocal Point = {}\nPoint.__index = Point\n\nse"
},
{
"path": "nim/algo.nim",
"chars": 1524,
"preview": "import math, hashes, tables, sequtils\n\ntype\n Point* = tuple[x, y: float]\n Points* = seq[Point]\n Centroids = open"
},
{
"path": "nim/benchmark.nim",
"chars": 664,
"preview": "import times, json, math, strutils, algo\n\nconst\n n = 10\n iterations = 100\n filename = \"../points.json\"\n\nproc loadPoin"
},
{
"path": "node/kmeans.js",
"chars": 1150,
"preview": "var _ = require(\"lodash\");\nvar fs = require(\"fs\");\n\nfunction sq(x) { return x * x }\n\nfunction dist(x, y) {\n return Math"
},
{
"path": "node/package.json",
"chars": 65,
"preview": "{\n \"name\": \"kmeans\",\n \"dependencies\": {\n \"lodash\": \"*\"\n }\n}"
},
{
"path": "ocaml/kmeans.ml",
"chars": 1025,
"preview": "open Core.Std\nopen Point\n\nlet min_by f xs =\n let Some h = List.hd xs in\n let m = f h in\n let (_, min_elt) = List.fold"
},
{
"path": "ocaml/kmeans.mli",
"chars": 71,
"preview": "open Core.Std\n\nval run: Point.t list -> int -> int -> Point.t list list"
},
{
"path": "ocaml/main.ml",
"chars": 698,
"preview": "open Core.Std\n\nlet read_point json =\n let open Yojson.Basic.Util in\n let open Point in\n let [x; y] = List.map (json |"
},
{
"path": "ocaml/point.ml",
"chars": 339,
"preview": "open Core.Std\n\ntype t = { x: float; y: float }\n\nlet ( ++ ) { x = x1; y = y1 } { x = x2; y = y2 } = { x = x1 +. x2; y = y"
},
{
"path": "opencl/.gitignore",
"chars": 6,
"preview": "kmeans"
},
{
"path": "opencl/kmeans.cl",
"chars": 2504,
"preview": "#include \"point.h\"\n\n\nfloat dist(__global Point* p, __global Centroid* c)\n{\n float dx = p->x - c->x;\n float dy = p-"
},
{
"path": "opencl/kmeans.nim",
"chars": 2259,
"preview": "import times, json, os, math, strutils, opencl, util, point\n\nproc loadPoints(filename: string): seq[Point] =\n result = "
},
{
"path": "opencl/kmeans.nimble",
"chars": 626,
"preview": "mode = ScriptMode.Verbose\n\npackageName = \"kmeans-opencl\"\nversion = \"0.1.0\"\nauthor = \"Andrea Ferretti\"\ndes"
},
{
"path": "opencl/point.h",
"chars": 189,
"preview": "typedef struct {\n float x;\n float y;\n int cluster;\n} Point;\n\ntypedef struct {\n float x;\n float y;\n} Centroid;\n\ntype"
},
{
"path": "opencl/point.nim",
"chars": 204,
"preview": "type\n Point* = object\n x*: cfloat\n y*: cfloat\n cluster*: cint\n\n Centroid* = object\n x*: cfloat\n y*: cfl"
},
{
"path": "opencl/util.nim",
"chars": 6908,
"preview": "import opencl\n\ntype\n PlatformNotFound = object of Exception\n DeviceNotFound = object of Exception\n\nproc newPlatformNot"
},
{
"path": "openmp/compile.sh",
"chars": 285,
"preview": "gcc -Wall -O3 -c hashmap.c -o hashmap.o `pkg-config --cflags --libs glib-2.0`\ngcc -Wall -O3 -c kmeans.c -o kmeans.o\ngcc "
},
{
"path": "openmp/makefile",
"chars": 807,
"preview": "#\n# build the openmp project.\n#\n# usage:\n# normal build:\n# $make\n#\n# clean project:\n# $make clean\n# \n# @author"
},
{
"path": "openmp/src/config.h",
"chars": 620,
"preview": "#ifndef CONFIGURATION_H_INCLUIDED\n#define CONFIGURATION_H_INCLUIDED\n\n// set to 1 if you want run repository specificatio"
},
{
"path": "openmp/src/kmeans.c",
"chars": 2266,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n\n#include \"kmeans.h\"\n#include \"point.h\"\n#include <omp.h>\n#include \"config.h\"\n\n\nvo"
},
{
"path": "openmp/src/kmeans.h",
"chars": 159,
"preview": "#ifndef KMEANS_H_INCLUDED\n#define KMEANS_H_INCLUDED\n\n#include \"point.h\"\n\nvoid km_execute(Point* h_points, Centroid* h_ce"
},
{
"path": "openmp/src/main.c",
"chars": 3653,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n\n#include \"point.h\"\n\n#include <string.h>\n#include <jansson.h>\n#include <sys/time."
},
{
"path": "openmp/src/point.c",
"chars": 640,
"preview": "#include <math.h>\n#include \"point.h\"\n#include <stdlib.h>\n#include <stdio.h>\n#include <omp.h>\n\nvoid divide(Point* p, long"
},
{
"path": "openmp/src/point.h",
"chars": 457,
"preview": "#ifndef POINT_H_INCLUDED\n#define POINT_H_INCLUDED\n\ntypedef struct {\n double x;\n double y;\n int centroid;\n} Poin"
},
{
"path": "parasail/benchmark.psl",
"chars": 432,
"preview": "func main (Args: Basic_Array <Univ_String>) is\n var R := Random::Start(11)\n var S := Random::Start(12)\n var Points: V"
},
{
"path": "parasail/kmeans.psl",
"chars": 1943,
"preview": "interface KMeans<> is\n func Run(PS: Vector<Point>; N: Univ_Integer; Iters: Univ_Integer) -> Vector<Vector<Point>>\nend i"
},
{
"path": "parasail/point.psl",
"chars": 1652,
"preview": "interface Point<> is\n func New(X: Univ_Real; Y: Univ_Real) -> Point\n\n func To_String(P: Point) -> Univ_String\n func P"
},
{
"path": "perl/kmeans.pl",
"chars": 1509,
"preview": "#!/usr/bin/env perl\n\nuse warnings;\nuse strict;\nuse 5.20.0;\nuse JSON;\nuse List::Util qw(reduce);\n\nopen my $POINTS, '<', '"
},
{
"path": "pharo3/KMeans.st",
"chars": 3118,
"preview": "Object subclass: #KMeans\r\tinstanceVariableNames: 'iterations clusters'\r\tclassVariableNames: ''\r\tpoolDictionaries: ''\r\tca"
},
{
"path": "points.json",
"chars": 3962094,
"preview": "[[2.2468149848067736,2.378003715119896],[2.1650033831423943,2.122084074657848],[1.1260092728223317,0.8295179778023649],["
},
{
"path": "pony/.gitignore",
"chars": 3,
"preview": "bin"
},
{
"path": "pony/Makefile",
"chars": 80,
"preview": "\ndefault: all\n\nclean:\n\trm -rf bin\n\nall:\n\tponyc kmeans -o bin\n\nrun:\n\t./bin/kmeans"
},
{
"path": "pony/kmeans/main.pony",
"chars": 2491,
"preview": "use \"collections\"\nuse \"time\"\nuse \"files\"\nuse \"json\"\n\ntype Point is (F64, F64)\n\nactor Main\n\n let n : USize = 10"
},
{
"path": "python/kmeans.py",
"chars": 1568,
"preview": "from collections import defaultdict\nfrom math import sqrt\nfrom time import time\nimport json\n\n\nclass Point(object):\n x"
},
{
"path": "results",
"chars": 2888,
"preview": "setup\n=====\n\nsingle thread\n100000 points\n10 clusters\n15 iterations\naverage over 100 repetitions\n\nmachine info\n=========="
},
{
"path": "ruby/kmeans.rb",
"chars": 1246,
"preview": "require 'json'\n\nclass Point\n attr_accessor :x\n attr_accessor :y\n\n def initialize(x, y)\n @x = x\n @y = y\n end\n\n "
},
{
"path": "rust/.gitignore",
"chars": 11,
"preview": "Cargo.lock\n"
},
{
"path": "rust/Cargo.toml",
"chars": 286,
"preview": "[package]\n\nname = \"kmeans\"\nversion = \"0.1.2\"\nauthors = [ \"Andrea Ferretti <ferrettiandrea@gmail.com>\" ]\n\n\n[lib]\nname = \""
},
{
"path": "rust/src/algo.rs",
"chars": 1507,
"preview": "use std::collections::HashMap;\nuse std::collections::hash_map::Entry::{Occupied, Vacant};\n\nuse point::Point;\n\nfn dist(v:"
},
{
"path": "rust/src/lib.rs",
"chars": 70,
"preview": "#[macro_use]\nextern crate serde_derive;\n\npub mod point;\npub mod algo;\n"
},
{
"path": "rust/src/main.rs",
"chars": 862,
"preview": "extern crate time;\nextern crate kmeans;\n\nextern crate serde;\nextern crate serde_json;\n\nuse std::path::Path;\nuse std::fs:"
},
{
"path": "rust/src/point.rs",
"chars": 1449,
"preview": "extern crate serde;\nextern crate serde_json;\n\nuse std::hash::{Hash, Hasher};\nuse std::mem;\nuse std::ops::{Add, Sub};\n\n#["
},
{
"path": "scala/build.sbt",
"chars": 305,
"preview": "name := \"kmeans\"\n\norganization := \"unicredit\"\n\nversion := \"0.1-SNAPSHOT\"\n\nscalaVersion := \"2.11.7\"\n\nscalacOptions ++= Se"
},
{
"path": "scala/src/main/scala/kmeans/Algo.scala",
"chars": 856,
"preview": "package kmeans\n\nimport math.sqrt\n\n\nobject Algo {\n val n = 10\n val iters = 15\n\n class Point(val x: Double, val y: Doub"
},
{
"path": "scala/src/main/scala/kmeans/Main.scala",
"chars": 653,
"preview": "package kmeans\n\nimport scala.io.Source\nimport org.json4s._\nimport org.json4s.jackson.JsonMethods._\n\n\nobject Main extends"
},
{
"path": "scala-js/.gitignore",
"chars": 22,
"preview": "target\nproject/target\n"
},
{
"path": "scala-js/build.sbt",
"chars": 368,
"preview": " enablePlugins(ScalaJSPlugin)\n\nname := \"kmeans\"\n\norganization := \"unicredit\"\n\nversion := \"0.1-SNAPSHOT\"\n\nscalaVersion :="
},
{
"path": "scala-js/project/build.properties",
"chars": 20,
"preview": "sbt.version=0.13.11\n"
},
{
"path": "scala-js/project/plugins.sbt",
"chars": 56,
"preview": "addSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % \"0.6.13\")\n"
},
{
"path": "scala-js/src/main/scala/kmeans/Algo.scala",
"chars": 856,
"preview": "package kmeans\n\nimport math.sqrt\n\n\nobject Algo {\n val n = 10\n val iters = 15\n\n class Point(val x: Double, val y: Doub"
},
{
"path": "scala-js/src/main/scala/kmeans/Main.scala",
"chars": 854,
"preview": "package kmeans\n\nimport scala.io.Source\nimport scala.scalajs.js\n\n\nobject Main extends js.JSApp {\n def readPoints(path: S"
},
{
"path": "scala-native/build.sbt",
"chars": 77,
"preview": "enablePlugins(ScalaNativePlugin)\n\nname := \"kmeans\"\n\nscalaVersion := \"2.11.8\"\n"
},
{
"path": "scala-native/project/build.properties",
"chars": 20,
"preview": "sbt.version=0.13.11\n"
},
{
"path": "scala-native/project/plugins.sbt",
"chars": 114,
"preview": "resolvers += Resolver.sonatypeRepo(\"snapshots\")\n\naddSbtPlugin(\"org.scala-native\" % \"sbtplugin\" % \"0.1-SNAPSHOT\")\n"
},
{
"path": "scala-native/src/main/scala/kmeans/Algo.scala",
"chars": 1167,
"preview": "package kmeans\n\nimport java.lang.Math.sqrt\n\nobject Algo {\n val n = 10\n val iters = 15\n\n class Point(val x: Double, va"
},
{
"path": "scala-native/src/main/scala/kmeans/Main.scala",
"chars": 1156,
"preview": "package kmeans\n\nimport scalanative.native._, stdlib._, stdio._\n\nimport Jansson._\nimport SysTime._\nimport Algo.Point\n\nobj"
},
{
"path": "scala-native/src/main/scala/kmeans/native.scala",
"chars": 885,
"preview": "package kmeans\n\nimport scalanative.native._\n\n@link(\"jansson\")\n@extern object Jansson {\n // in C enums become ints at ru"
},
{
"path": "stanza/compile.sh",
"chars": 83,
"preview": "stanza kmeans.stanza -ccfiles kmeansutils.c -ccflags -ljansson -o kmeans -optimize\n"
},
{
"path": "stanza/kmeans.stanza",
"chars": 3008,
"preview": "defpackage kmeans :\n import core\n import math\n import collections\n\ndefstruct Point <: Hashable & Equalable :\n x:"
},
{
"path": "stanza/kmeansutils.c",
"chars": 787,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n\n#include <string.h>\n#include <jansson.h>\n#include <sys/time.h>\n\nlong int getTime"
},
{
"path": "swift/.gitignore",
"chars": 5,
"preview": "main\n"
},
{
"path": "swift/kmeans.swift",
"chars": 1915,
"preview": "#if os(Linux)\n import Glibc\n#else\n import Darwin\n#endif\n\nstruct Point : Equatable {\n let x: Double\n let y: Double\n\n\n"
},
{
"path": "swift/main.swift",
"chars": 661,
"preview": "import Foundation\n\nlet path = \"../points.json\"\nlet jsonFile = NSData(contentsOfFile: path)!\nlet jsonData = (try? NSJSONS"
},
{
"path": "x10/CJson.x10",
"chars": 406,
"preview": "import x10.compiler.Native;\nimport x10.compiler.NativeCPPInclude;\nimport x10.compiler.NativeCPPCompilationUnit;\n\n@Native"
},
{
"path": "x10/KMeans.x10",
"chars": 2231,
"preview": "import x10.regionarray.Array;\nimport x10.util.HashMap;\nimport x10.util.ArrayList;\nimport x10.util.RailUtils;\n\npublic cla"
},
{
"path": "x10/Main.x10",
"chars": 712,
"preview": "import x10.regionarray.Array;\nimport x10.compiler.Native;\n\npublic class Main {\n\n\tstatic val times = 100;\n\n\tpublic static"
},
{
"path": "x10/Makefile",
"chars": 511,
"preview": "MAKEFLAGS = --no-print-directory\n\nTARGETS = \\\n\n#default: all\n\nclean: FORCE\n\trm -f javabin/*.*\n\trm -f cbin/*.*\n\trm -f jav"
},
{
"path": "x10/RichPoint.x10",
"chars": 416,
"preview": "public struct RichPoint {\n\tval x : Double; \n\tval y:Double;\n\t\n\tdef this(x:Double, y:Double) {\n\t\tthis.x = x; this.y = y;\n\t"
},
{
"path": "x10/jsonRead.cc",
"chars": 611,
"preview": "#include <cstdlib>\n#include <cstdio>\n#include <jansson.h>\n\ndouble c_xs[100000];\ndouble c_ys[100000];\nint c_xs_counter = "
},
{
"path": "x10/jsonRead.h",
"chars": 47,
"preview": "\nvoid parse();\n\ndouble nextX();\ndouble nextY();"
},
{
"path": "x10/jsonRead.java",
"chars": 1305,
"preview": "\npublic class jsonRead {\n\n\tstatic double[] java_xs = new double[100000];\n\tstatic int java_xs_counter = 0;\n static dou"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the andreaferretti/kmeans GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 137 files (3.9 MB), approximately 1.0M tokens, and a symbol index with 178 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.