cluster_eval 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9de67d89a54d6c2bf313a057797e3b56c74f0c6c
4
+ data.tar.gz: 4d5c3e6d8a5765078a214c8a14234e21526d8659
5
+ SHA512:
6
+ metadata.gz: d8b451b4f4f0e123ff50bc276e5870969ac067348ac36789a25f8269fff769b2dbd00fbc76ab908478c39865e509804a94b15ba88228e4c6bfd2800d1ff56c1c
7
+ data.tar.gz: 662a605c5267911780356e2f4727f424addd0971457797075458d787ead697f1e92b534bae5100318b050bd39cdf160b4bddb4a489121bcc2f07f03a0c7774ca
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ *~
2
+ *.o
3
+ *.so
4
+ Makefile
5
+ ext/test.rb
6
+ /.bundle/
7
+ /.yardoc
8
+ /Gemfile.lock
9
+ /_yardoc/
10
+ /coverage/
11
+ /doc/
12
+ /pkg/
13
+ /spec/reports/
14
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,24 @@
1
+ language: ruby
2
+ compiler: gcc
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.1
7
+ - ruby-head
8
+
9
+ before_install:
10
+ - gem install thor
11
+ - gem install rice
12
+ - gem install bundler
13
+ - gem install rake
14
+ - gem install minitest
15
+ - gem install minitest-reporters
16
+ - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
17
+ - sudo apt-get update -qq
18
+ - sudo apt-get install -qq g++-4.8
19
+ - export CXX="g++-4.8"
20
+ - export CC="gcc-4.8"
21
+ - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90
22
+
23
+ install:
24
+ - cd ext/ && ruby extconf.rb && make
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cluster_eval.gemspec
4
+ gemspec
5
+
6
+ gem "bundler", "~> 1.8"
7
+ gem "rake", "~> 10.0"
8
+ gem "minitest", "~> 5.4"
9
+ gem "minitest-reporters", "~> 1.0"
10
+ gem 'thor', '~> 0.19'
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # ClusterEval
2
+
3
+ Evaluates clusterings of a dataset using a variety of scores.
4
+
5
+ [![Build Status](https://travis-ci.org/sbonisso/cluster_eval.svg?branch=master)](https://travis-ci.org/sbonisso/cluster_eval)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'cluster_eval'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install cluster_eval
22
+
23
+ Note, you will need a version of g++ installed that is compatible with [C++11](https://gcc.gnu.org/projects/cxx0x.html).
24
+
25
+ ## Usage
26
+
27
+ This can be used as a library, or through the installed command line program `cluster_eval`.
28
+
29
+ ```
30
+ $ cluster_eval help eval
31
+ Usage:
32
+ cluster_eval eval [options]
33
+
34
+ Options:
35
+ -a, [--cluster-file-a=CLUSTER_FILE_A] # cluster file A
36
+ -b, [--cluster-file-b=CLUSTER_FILE_B] # cluster file B
37
+ -y, [--type=TYPE] # type of index to compute
38
+ ```
39
+
40
+ The `type` argument specifies the index to compute either the [Rand index](http://en.wikipedia.org/wiki/Rand_index), [Jaccard index](http://en.wikipedia.org/wiki/Jaccard_index), [Fowlkes-Mallows index](http://en.wikipedia.org/wiki/Fowlkes%E2%80%93Mallows_index), adjusted [Rand index](http://en.wikipedia.org/wiki/Rand_index#Adjusted_Rand_index), or all.
41
+ It can take on values of: [rand/jaccard/fm/adj_rand/all]
42
+
43
+ Each cluster file must contain two columns of integers, the first column representing the sample ID, the second column the cluster ID. The sample IDs need not be sorted, but must contain all sample IDs from 0 to n samples.
44
+
45
+ For example if we have two files clust_a.tab and clust_b.tab, we could run the following:
46
+
47
+ ```
48
+ $ cluster_eval eval -a clust_a.tab -b clust_b.tab -y rand
49
+ 0.643
50
+ $ cluster_eval eval -a clust_a.tab -b clust_b.tab -y jaccard
51
+ 0.286
52
+ $ cluster_eval eval -a clust_a.tab -b clust_b.tab -y fm
53
+ 0.456
54
+ $ cluster_eval eval -a clust_a.tab -b clust_b.tab -y adj_rand
55
+ 0.200
56
+ $ cluster_eval eval -a clust_a.tab -b clust_b.tab -y all
57
+ rand jaccard fm adj_rand
58
+ 0.643 0.286 0.456 0.200
59
+ ```
60
+
61
+
62
+ ## Development
63
+
64
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
65
+
66
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it ( https://github.com/[my-github-username]/cluster_eval/fork )
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
73
+ 4. Push to the branch (`git push origin my-new-feature`)
74
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new(:all) do |t|
7
+ t.pattern = "tests/test_*.rb"
8
+ end
9
+
10
+ task :default => :all
data/bin/cluster_eval ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'thor'
4
+ require 'cluster_eval'
5
+
6
+ class CLUSTER_EVAL_BIN < Thor
7
+
8
+ method_option :cluster_file_a, :aliases => "-a", :desc => "cluster file A"
9
+ method_option :cluster_file_b, :aliases => "-b", :desc => "cluster file B"
10
+ method_option :type, :aliases => "-y",
11
+ :desc => "type of index to compute [rand/jaccard/fm/adj_rand/all]"
12
+ desc 'eval [options]', 'evaluate clusterings'
13
+ def eval()
14
+ clust_a_f = options["cluster_file_a"]
15
+ clust_b_f = options["cluster_file_b"]
16
+ index_type = options["type"]
17
+
18
+ clust_a_h = {}
19
+ IO.foreach(clust_a_f) do |line|
20
+ ary = line.chomp.split("\t")
21
+ clust_a_h[ary[0].to_i] = ary[1].to_i
22
+ end
23
+ clust_b_h = {}
24
+ IO.foreach(clust_b_f) do |line|
25
+ ary = line.chomp.split("\t")
26
+ clust_b_h[ary[0].to_i] = ary[1].to_i
27
+ end
28
+
29
+ cm = ClusterEval::ConfusionMatrix.new(clust_a_h, clust_b_h)
30
+
31
+ if index_type == "rand" then
32
+ puts '%0.3f' % cm.get_rand_index
33
+ elsif index_type == "jaccard" then
34
+ puts '%0.3f' % cm.get_jaccard_index
35
+ elsif index_type == "fm" then
36
+ puts '%0.3f' % cm.get_fm_index
37
+ elsif index_type == "adj_rand" then
38
+ puts '%0.3f' % cm.get_adj_rand_index
39
+ elsif index_type == "all" then
40
+ puts ['rand', 'jaccard', 'fm', 'adj_rand'].join("\t")
41
+ puts ['%0.3f' % cm.get_rand_index,
42
+ '%0.3f' % cm.get_jaccard_index,
43
+ '%0.3f' % cm.get_fm_index,
44
+ '%0.3f' % cm.get_adj_rand_index].join("\t")
45
+ else
46
+ raise 'invalid index type'
47
+ end
48
+ end
49
+
50
+ end
51
+ #
52
+ CLUSTER_EVAL_BIN.start(ARGV)
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "cluster_eval"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cluster_eval/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cluster_eval"
8
+ spec.version = ClusterEval::VERSION
9
+ spec.authors = ["sbonisso"]
10
+ spec.email = ["sbonisso@ucsd.edu"]
11
+
12
+ # if spec.respond_to?(:metadata)
13
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com' to prevent pushes to rubygems.org, or delete to allow pushes to any server."
14
+ # end
15
+
16
+ spec.summary = %q{Evaluation of clusterings}
17
+ spec.description = %q{Evaluate partitionings of different clustering approaches. Provides different metrics to use.}
18
+ spec.homepage = "https://github.com/sbonisso/cluster_eval"
19
+ spec.license = "MIT"
20
+
21
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
22
+ spec.bindir = "bin"
23
+ #spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
+ spec.executables = "cluster_eval"
25
+ spec.require_paths = ["lib", "ext"]
26
+ spec.extensions = ["ext/extconf.rb"]
27
+
28
+ spec.add_dependency "thor", '~> 0.19'
29
+ spec.add_dependency "rice", '~> 1.7'
30
+
31
+ spec.add_development_dependency "bundler", "~> 1.8"
32
+ spec.add_development_dependency "rake", "~> 10.0"
33
+ spec.add_development_dependency "minitest", "~> 5.4"
34
+ spec.add_development_dependency "minitest-reporters", "~> 1.0"
35
+ end
@@ -0,0 +1,191 @@
1
+ #include "ConfusionMatrix.hpp"
2
+ /**
3
+ *
4
+ */
5
+ ConfusionMatrix::ConfusionMatrix() {
6
+ a_ = 0;
7
+ b_ = 0;
8
+ c_ = 0;
9
+ d_ = 0;
10
+ }
11
+ /**
12
+ *
13
+ */
14
+ ConfusionMatrix::~ConfusionMatrix() {}
15
+ /**
16
+ * each ruby hash are pairs of {read_id => clust_id}
17
+ */
18
+ ConfusionMatrix::ConfusionMatrix(Rice::Hash c1_hsh, Rice::Hash c2_hsh) {
19
+ a_ = 0;
20
+ b_ = 0;
21
+ c_ = 0;
22
+ d_ = 0;
23
+ populate_vect(c1_hsh, clust_1_);
24
+ populate_vect(c2_hsh, clust_2_);
25
+ //
26
+ int max_clust_1 = 0;
27
+ for(int i = 0; i < (int)clust_1_.size(); i++) {
28
+ if(clust_1_[i] > max_clust_1) {
29
+ max_clust_1 = clust_1_[i];
30
+ }
31
+ }
32
+ int max_clust_2 = 0;
33
+ for(int i = 0; i < (int)clust_2_.size(); i++) {
34
+ if(clust_2_[i] > max_clust_2) {
35
+ max_clust_2 = clust_2_[i];
36
+ }
37
+ }
38
+ // set up clust_id => [id_1, id_2, ...]
39
+ clust_map_1_.resize(max_clust_1+1);
40
+ clust_map_2_.resize(max_clust_2+1);
41
+ //
42
+ for(int i = 0; i < (int)clust_1_.size(); i++) {
43
+ clust_map_1_[clust_1_[i]].push_back(i);
44
+ }
45
+ for(int i = 0; i < (int)clust_2_.size(); i++) {
46
+ clust_map_2_[clust_2_[i]].push_back(i);
47
+ }
48
+ //
49
+ compute_confusion_matrix();
50
+ }
51
+ /**
52
+ * given a ruby hash, populate a vector of read_id as index, cluster_id as value
53
+ */
54
+ void ConfusionMatrix::populate_vect(Rice::Hash &hsh,
55
+ std::vector<int> &clust_v) {
56
+ int len = hsh.size();
57
+ clust_v.resize(len);
58
+ //
59
+ Rice::Hash::iterator it = hsh.begin();
60
+ Rice::Hash::iterator it_end = hsh.end();
61
+ int i = 0;
62
+ for(; it != it_end; ++it) {
63
+ Rice::Hash::Entry en(*it);
64
+ int x = FIX2INT(en.key);
65
+ int y = FIX2INT(en.value.value());
66
+ clust_v[x] = y;
67
+ i++;
68
+ }
69
+ }
70
+ /**
71
+ *
72
+ */
73
+ void ConfusionMatrix::print_matrix() {
74
+ std::cout<<a_<<"\t"<<b_<<"\t"<<c_<<"\t"<<d_<<std::endl;
75
+ }
76
+ /**
77
+ * return ruby array with contents of confusion matrix: [a, b, c, d]
78
+ */
79
+ Rice::Array ConfusionMatrix::get_confusion_matrix() {
80
+ Rice::Array ary;
81
+ ary.push(a_);
82
+ ary.push(b_);
83
+ ary.push(c_);
84
+ ary.push(d_);
85
+ return ary;
86
+ }
87
+ /**
88
+ * compute confusion matrix entries a, b, c, and d
89
+ * for the matrix:
90
+ * ---------
91
+ * | a | b |
92
+ * ---------
93
+ * | c | d |
94
+ * -------
95
+ */
96
+ void ConfusionMatrix::compute_confusion_matrix() {
97
+ std::pair<int,int> v1 = int_and_diff(clust_1_, clust_map_2_);
98
+ std::pair<int,int> v2 = int_and_diff(clust_2_, clust_map_1_);
99
+ //
100
+ int n = (int)clust_1_.size();
101
+ a_ = v1.first;
102
+ c_ = v1.second;
103
+ b_ = v2.second;
104
+ d_ = ((n*(n-1))/2) - (a_+c_+b_);
105
+ }
106
+ /**
107
+ * return Rand index: (a+b)/(a+b+c+d)
108
+ */
109
+ double ConfusionMatrix::get_rand_index() {
110
+ return (double)(a_+d_)/(double)(a_+b_+c_+d_);
111
+ }
112
+ /**
113
+ * return Jaccard index: a/(a+c+b)
114
+ */
115
+ double ConfusionMatrix::get_jaccard_index() {
116
+ return (double)(a_)/(double)(a_+c_+b_);
117
+ }
118
+ /**
119
+ * returns Fowlkes-Mallows (FM) index: a/sqrt((a+c)*(a+b))
120
+ */
121
+ double ConfusionMatrix::get_fm_index() {
122
+ double d1 = (double)(a_+c_);
123
+ double d2 = (double)(a_+b_);
124
+ return (double)a_/sqrt(d1*d2);
125
+ }
126
+ /**
127
+ * returns the adjusted Rand index using the confusion matrix
128
+ */
129
+ double ConfusionMatrix::get_adj_rand_index() {
130
+ double total = a_+b_+c_+d_;
131
+ double n1 = ((b_+a_)*(c_+a_) + (b_+d_)*(c_+d_));
132
+
133
+ double num = (total*((double)(a_+d_))) - n1;
134
+ double denom = (total*total - n1);
135
+ return (num/denom);
136
+ }
137
+ /**
138
+ * get counts of: <intersection, difference> between the vector of
139
+ * cluster assignments (A) and cluster assignment groupings (B)
140
+ */
141
+ std::pair<int,int> ConfusionMatrix::int_and_diff(std::vector<int> clust_v,
142
+ std::vector<std::vector<int>> clust_map) {
143
+ //
144
+ int intsect = 0;
145
+ int diff = 0;
146
+ for(int i = 0; i < (int)clust_map.size(); i++) {
147
+ //
148
+ std::vector<int> vs = clust_map[i];
149
+ int len = (int) vs.size();
150
+ for(int i = 0; i < len; i++) {
151
+ int val_i = vs[i];
152
+ for(int j = 0; j < len; j++) {
153
+ if(i < j) {
154
+ int val_j = vs[j];
155
+ bool t1 = clust_v[val_i] == clust_v[val_j];
156
+ if(t1) { intsect++; }
157
+ else { diff++; }
158
+ }
159
+ }
160
+ }
161
+ }
162
+ //
163
+ return std::pair<int,int>(intsect, diff);
164
+ }
165
+ /**
166
+ * compute confusion matrix in naive N**2 time, used for comparing
167
+ * (i.e., sanity check) testing results
168
+ */
169
+ Rice::Array ConfusionMatrix::get_confusion_matrix_naive() {
170
+ int len = (int)clust_1_.size();
171
+ int a = 0; int b = 0; int c = 0; int d = 0;
172
+ for(int i = 0; i < len; i++) {
173
+ for(int j = 0; j < len; j++) {
174
+ if(i >= j) { continue; }
175
+ bool t1 = (clust_1_[i] == clust_1_[j]);
176
+ bool t2 = (clust_2_[i] == clust_2_[j]);
177
+ if(t1 && t2) { a += 1; }
178
+ else if(!t1 && !t2) { d += 1; }
179
+ else if(!t1 && t2) { c += 1; }
180
+ else if(t1 && !t2) { b += 1; }
181
+ else {}
182
+ }
183
+ }
184
+ //
185
+ Rice::Array ary;
186
+ ary.push(a);
187
+ ary.push(b);
188
+ ary.push(c);
189
+ ary.push(d);
190
+ return ary;
191
+ }
@@ -0,0 +1,56 @@
1
+ #ifndef CONFUSION_MATRIX_HPP
2
+ #define CONFUSION_MATRIX_HPP
3
+
4
+ #include <iostream>
5
+ #include <string>
6
+ #include <vector>
7
+ #include <utility>
8
+ #include <cmath>
9
+ #include "prettyprint.hpp"
10
+
11
+ #ifndef CPPPROG
12
+ #include "rice/String.hpp"
13
+ #include "rice/Array.hpp"
14
+ #include "rice/Hash.hpp"
15
+ #endif
16
+
17
+ class ConfusionMatrix {
18
+ protected:
19
+
20
+ void compute_confusion_matrix();
21
+ int a_;
22
+ int b_;
23
+ int c_;
24
+ int d_;
25
+ //
26
+ std::vector<int> clust_1_;
27
+ std::vector<int> clust_2_;
28
+ //
29
+ std::vector<std::vector<int> > clust_map_1_;
30
+ std::vector<std::vector<int> > clust_map_2_;
31
+ // fill in clust_vect from hash (ruby hash)
32
+ void populate_vect(Rice::Hash &hsh, std::vector<int> &clust_v);
33
+ //
34
+ std::pair<int,int> int_and_diff(std::vector<int> clust_v,
35
+ std::vector<std::vector<int>> clust_map);
36
+
37
+ public:
38
+ ConfusionMatrix();
39
+ ConfusionMatrix(Rice::Hash c1_hsh, Rice::Hash c2_hsh);
40
+ virtual ~ConfusionMatrix();
41
+
42
+ void print_matrix();
43
+
44
+ Rice::Array get_confusion_matrix();
45
+ // for computing various indices
46
+ double get_rand_index();
47
+ double get_jaccard_index();
48
+ double get_fm_index();
49
+ double get_adj_rand_index();
50
+
51
+ // compute using naive N^2 for testing purposes
52
+ Rice::Array get_confusion_matrix_naive();
53
+
54
+ };
55
+
56
+ #endif
data/ext/clusteval.cpp ADDED
@@ -0,0 +1,25 @@
1
+ #include "rice/Data_Type.hpp"
2
+ #include "rice/Constructor.hpp"
3
+ #include "rice/Hash.hpp"
4
+ #include "ConfusionMatrix.hpp"
5
+
6
+ using namespace Rice;
7
+
8
+ extern "C"
9
+
10
+ void Init_ClusterEval()
11
+ {
12
+ Module rb_cModule = define_module("ClusterEval");
13
+ Data_Type<ConfusionMatrix> rb_cConfusionMatrix =
14
+ define_class_under<ConfusionMatrix>(rb_cModule,"ConfusionMatrix")
15
+ .define_constructor(Constructor<ConfusionMatrix>())
16
+ //.define_constructor(Constructor<ConfusionMatrix,std::string,std::string>())
17
+ .define_constructor(Constructor<ConfusionMatrix,Hash,Hash>())
18
+ .define_method("get_rand_index", &ConfusionMatrix::get_rand_index)
19
+ .define_method("get_jaccard_index", &ConfusionMatrix::get_jaccard_index)
20
+ .define_method("get_fm_index", &ConfusionMatrix::get_fm_index)
21
+ .define_method("get_adj_rand_index", &ConfusionMatrix::get_adj_rand_index)
22
+ .define_method("print_matrix", &ConfusionMatrix::print_matrix)
23
+ .define_method("get_confusion_matrix", &ConfusionMatrix::get_confusion_matrix)
24
+ .define_method("get_confusion_matrix_naive", &ConfusionMatrix::get_confusion_matrix_naive);
25
+ }
data/ext/extconf.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'mkmf-rice'
2
+
3
+ $CPPFLAGS << ' -std=c++11'
4
+ $CPPFLAGS << ' -Wno-deprecated'
5
+
6
+ $warnflags = $warnflags.split("-Wimplicit-function-declaration").join(" ")
7
+ $warnflags = $warnflags.split("-Wdeclaration-after-statement").join(" ")
8
+
9
+ create_makefile('ClusterEval')
@@ -0,0 +1,445 @@
1
+ // Copyright Louis Delacroix 2010 - 2014.
2
+ // Distributed under the Boost Software License, Version 1.0.
3
+ // (See accompanying file LICENSE_1_0.txt or copy at
4
+ // http://www.boost.org/LICENSE_1_0.txt)
5
+ //
6
+ // A pretty printing library for C++
7
+ //
8
+ // Usage:
9
+ // Include this header, and operator<< will "just work".
10
+
11
+ #ifndef H_PRETTY_PRINT
12
+ #define H_PRETTY_PRINT
13
+
14
+ #include <cstddef>
15
+ #include <iterator>
16
+ #include <memory>
17
+ #include <ostream>
18
+ #include <set>
19
+ #include <tuple>
20
+ #include <type_traits>
21
+ #include <unordered_set>
22
+ #include <utility>
23
+ #include <valarray>
24
+
25
+ namespace pretty_print
26
+ {
27
+ namespace detail
28
+ {
29
+ // SFINAE type trait to detect whether T::const_iterator exists.
30
+
31
+ struct sfinae_base
32
+ {
33
+ using yes = char;
34
+ using no = yes[2];
35
+ };
36
+
37
+ template <typename T>
38
+ struct has_const_iterator : private sfinae_base
39
+ {
40
+ private:
41
+ template <typename C> static yes & test(typename C::const_iterator*);
42
+ template <typename C> static no & test(...);
43
+ public:
44
+ static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
45
+ using type = T;
46
+ };
47
+
48
+ template <typename T>
49
+ struct has_begin_end : private sfinae_base
50
+ {
51
+ private:
52
+ template <typename C>
53
+ static yes & f(typename std::enable_if<
54
+ std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::begin)),
55
+ typename C::const_iterator(C::*)() const>::value>::type *);
56
+
57
+ template <typename C> static no & f(...);
58
+
59
+ template <typename C>
60
+ static yes & g(typename std::enable_if<
61
+ std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::end)),
62
+ typename C::const_iterator(C::*)() const>::value, void>::type*);
63
+
64
+ template <typename C> static no & g(...);
65
+
66
+ public:
67
+ static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
68
+ static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
69
+ };
70
+
71
+ } // namespace detail
72
+
73
+
74
+ // Holds the delimiter values for a specific character type
75
+
76
+ template <typename TChar>
77
+ struct delimiters_values
78
+ {
79
+ using char_type = TChar;
80
+ const char_type * prefix;
81
+ const char_type * delimiter;
82
+ const char_type * postfix;
83
+ };
84
+
85
+
86
+ // Defines the delimiter values for a specific container and character type
87
+
88
+ template <typename T, typename TChar>
89
+ struct delimiters
90
+ {
91
+ using type = delimiters_values<TChar>;
92
+ static const type values;
93
+ };
94
+
95
+
96
+ // Functor to print containers. You can use this directly if you want
97
+ // to specificy a non-default delimiters type. The printing logic can
98
+ // be customized by specializing the nested template.
99
+
100
+ template <typename T,
101
+ typename TChar = char,
102
+ typename TCharTraits = ::std::char_traits<TChar>,
103
+ typename TDelimiters = delimiters<T, TChar>>
104
+ struct print_container_helper
105
+ {
106
+ using delimiters_type = TDelimiters;
107
+ using ostream_type = std::basic_ostream<TChar, TCharTraits>;
108
+
109
+ template <typename U>
110
+ struct printer
111
+ {
112
+ static void print_body(const U & c, ostream_type & stream)
113
+ {
114
+ using std::begin;
115
+ using std::end;
116
+
117
+ auto it = begin(c);
118
+ const auto the_end = end(c);
119
+
120
+ if (it != the_end)
121
+ {
122
+ for ( ; ; )
123
+ {
124
+ stream << *it;
125
+
126
+ if (++it == the_end) break;
127
+
128
+ if (delimiters_type::values.delimiter != NULL)
129
+ stream << delimiters_type::values.delimiter;
130
+ }
131
+ }
132
+ }
133
+ };
134
+
135
+ print_container_helper(const T & container)
136
+ : container_(container)
137
+ { }
138
+
139
+ inline void operator()(ostream_type & stream) const
140
+ {
141
+ if (delimiters_type::values.prefix != NULL)
142
+ stream << delimiters_type::values.prefix;
143
+
144
+ printer<T>::print_body(container_, stream);
145
+
146
+ if (delimiters_type::values.postfix != NULL)
147
+ stream << delimiters_type::values.postfix;
148
+ }
149
+
150
+ private:
151
+ const T & container_;
152
+ };
153
+
154
+ // Specialization for pairs
155
+
156
+ template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
157
+ template <typename T1, typename T2>
158
+ struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::pair<T1, T2>>
159
+ {
160
+ using ostream_type = print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
161
+
162
+ static void print_body(const std::pair<T1, T2> & c, ostream_type & stream)
163
+ {
164
+ stream << c.first;
165
+ if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
166
+ stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
167
+ stream << c.second;
168
+ }
169
+ };
170
+
171
+ // Specialization for tuples
172
+
173
+ template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
174
+ template <typename ...Args>
175
+ struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::tuple<Args...>>
176
+ {
177
+ using ostream_type = print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
178
+ using element_type = std::tuple<Args...>;
179
+
180
+ template <std::size_t I> struct Int { };
181
+
182
+ static void print_body(const element_type & c, ostream_type & stream)
183
+ {
184
+ tuple_print(c, stream, Int<0>());
185
+ }
186
+
187
+ static void tuple_print(const element_type &, ostream_type &, Int<sizeof...(Args)>)
188
+ {
189
+ }
190
+
191
+ static void tuple_print(const element_type & c, ostream_type & stream,
192
+ typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type)
193
+ {
194
+ stream << std::get<0>(c);
195
+ tuple_print(c, stream, Int<1>());
196
+ }
197
+
198
+ template <std::size_t N>
199
+ static void tuple_print(const element_type & c, ostream_type & stream, Int<N>)
200
+ {
201
+ if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
202
+ stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
203
+
204
+ stream << std::get<N>(c);
205
+
206
+ tuple_print(c, stream, Int<N + 1>());
207
+ }
208
+ };
209
+
210
+ // Prints a print_container_helper to the specified stream.
211
+
212
+ template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
213
+ inline std::basic_ostream<TChar, TCharTraits> & operator<<(
214
+ std::basic_ostream<TChar, TCharTraits> & stream,
215
+ const print_container_helper<T, TChar, TCharTraits, TDelimiters> & helper)
216
+ {
217
+ helper(stream);
218
+ return stream;
219
+ }
220
+
221
+
222
+ // Basic is_container template; specialize to derive from std::true_type for all desired container types
223
+
224
+ template <typename T>
225
+ struct is_container : public std::integral_constant<bool,
226
+ detail::has_const_iterator<T>::value &&
227
+ detail::has_begin_end<T>::beg_value &&
228
+ detail::has_begin_end<T>::end_value> { };
229
+
230
+ template <typename T, std::size_t N>
231
+ struct is_container<T[N]> : std::true_type { };
232
+
233
+ template <std::size_t N>
234
+ struct is_container<char[N]> : std::false_type { };
235
+
236
+ template <typename T>
237
+ struct is_container<std::valarray<T>> : std::true_type { };
238
+
239
+ template <typename T1, typename T2>
240
+ struct is_container<std::pair<T1, T2>> : std::true_type { };
241
+
242
+ template <typename ...Args>
243
+ struct is_container<std::tuple<Args...>> : std::true_type { };
244
+
245
+
246
+ // Default delimiters
247
+
248
+ template <typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
249
+ template <typename T> const delimiters_values<char> delimiters<T, char>::values = { "[", ", ", "]" };
250
+ template <typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; };
251
+ template <typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"[", L", ", L"]" };
252
+
253
+
254
+ // Delimiters for (multi)set and unordered_(multi)set
255
+
256
+ template <typename T, typename TComp, typename TAllocator>
257
+ struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
258
+
259
+ template <typename T, typename TComp, typename TAllocator>
260
+ const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
261
+
262
+ template <typename T, typename TComp, typename TAllocator>
263
+ struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
264
+
265
+ template <typename T, typename TComp, typename TAllocator>
266
+ const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
267
+
268
+ template <typename T, typename TComp, typename TAllocator>
269
+ struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
270
+
271
+ template <typename T, typename TComp, typename TAllocator>
272
+ const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
273
+
274
+ template <typename T, typename TComp, typename TAllocator>
275
+ struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
276
+
277
+ template <typename T, typename TComp, typename TAllocator>
278
+ const delimiters_values<wchar_t> delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
279
+
280
+ template <typename T, typename THash, typename TEqual, typename TAllocator>
281
+ struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
282
+
283
+ template <typename T, typename THash, typename TEqual, typename TAllocator>
284
+ const delimiters_values<char> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
285
+
286
+ template <typename T, typename THash, typename TEqual, typename TAllocator>
287
+ struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
288
+
289
+ template <typename T, typename THash, typename TEqual, typename TAllocator>
290
+ const delimiters_values<wchar_t> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
291
+
292
+ template <typename T, typename THash, typename TEqual, typename TAllocator>
293
+ struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
294
+
295
+ template <typename T, typename THash, typename TEqual, typename TAllocator>
296
+ const delimiters_values<char> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
297
+
298
+ template <typename T, typename THash, typename TEqual, typename TAllocator>
299
+ struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
300
+
301
+ template <typename T, typename THash, typename TEqual, typename TAllocator>
302
+ const delimiters_values<wchar_t> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
303
+
304
+
305
+ // Delimiters for pair and tuple
306
+
307
+ template <typename T1, typename T2> struct delimiters<std::pair<T1, T2>, char> { static const delimiters_values<char> values; };
308
+ template <typename T1, typename T2> const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = { "(", ", ", ")" };
309
+ template <typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; };
310
+ template <typename T1, typename T2> const delimiters_values<wchar_t> delimiters< ::std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" };
311
+
312
+ template <typename ...Args> struct delimiters<std::tuple<Args...>, char> { static const delimiters_values<char> values; };
313
+ template <typename ...Args> const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values = { "(", ", ", ")" };
314
+ template <typename ...Args> struct delimiters< ::std::tuple<Args...>, wchar_t> { static const delimiters_values<wchar_t> values; };
315
+ template <typename ...Args> const delimiters_values<wchar_t> delimiters< ::std::tuple<Args...>, wchar_t>::values = { L"(", L", ", L")" };
316
+
317
+
318
+ // Type-erasing helper class for easy use of custom delimiters.
319
+ // Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar.
320
+ // Usage: "cout << pretty_print::custom_delims<MyDelims>(x)".
321
+
322
+ struct custom_delims_base
323
+ {
324
+ virtual ~custom_delims_base() { }
325
+ virtual std::ostream & stream(::std::ostream &) = 0;
326
+ virtual std::wostream & stream(::std::wostream &) = 0;
327
+ };
328
+
329
+ template <typename T, typename Delims>
330
+ struct custom_delims_wrapper : custom_delims_base
331
+ {
332
+ custom_delims_wrapper(const T & t_) : t(t_) { }
333
+
334
+ std::ostream & stream(std::ostream & s)
335
+ {
336
+ return s << print_container_helper<T, char, std::char_traits<char>, Delims>(t);
337
+ }
338
+
339
+ std::wostream & stream(std::wostream & s)
340
+ {
341
+ return s << print_container_helper<T, wchar_t, std::char_traits<wchar_t>, Delims>(t);
342
+ }
343
+
344
+ private:
345
+ const T & t;
346
+ };
347
+
348
+ template <typename Delims>
349
+ struct custom_delims
350
+ {
351
+ template <typename Container>
352
+ custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { }
353
+
354
+ std::unique_ptr<custom_delims_base> base;
355
+ };
356
+
357
+ template <typename TChar, typename TCharTraits, typename Delims>
358
+ inline std::basic_ostream<TChar, TCharTraits> & operator<<(std::basic_ostream<TChar, TCharTraits> & s, const custom_delims<Delims> & p)
359
+ {
360
+ return p.base->stream(s);
361
+ }
362
+
363
+
364
+ // A wrapper for a C-style array given as pointer-plus-size.
365
+ // Usage: std::cout << pretty_print_array(arr, n) << std::endl;
366
+
367
+ template<typename T>
368
+ struct array_wrapper_n
369
+ {
370
+ typedef const T * const_iterator;
371
+ typedef T value_type;
372
+
373
+ array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { }
374
+ inline const_iterator begin() const { return _array; }
375
+ inline const_iterator end() const { return _array + _n; }
376
+
377
+ private:
378
+ const T * const _array;
379
+ size_t _n;
380
+ };
381
+
382
+
383
+ // A wrapper for hash-table based containers that offer local iterators to each bucket.
384
+ // Usage: std::cout << bucket_print(m, 4) << std::endl; (Prints bucket 5 of container m.)
385
+
386
+ template <typename T>
387
+ struct bucket_print_wrapper
388
+ {
389
+ typedef typename T::const_local_iterator const_iterator;
390
+ typedef typename T::size_type size_type;
391
+
392
+ const_iterator begin() const
393
+ {
394
+ return m_map.cbegin(n);
395
+ }
396
+
397
+ const_iterator end() const
398
+ {
399
+ return m_map.cend(n);
400
+ }
401
+
402
+ bucket_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { }
403
+
404
+ private:
405
+ const T & m_map;
406
+ const size_type n;
407
+ };
408
+
409
+ } // namespace pretty_print
410
+
411
+
412
+ // Global accessor functions for the convenience wrappers
413
+
414
+ template<typename T>
415
+ inline pretty_print::array_wrapper_n<T> pretty_print_array(const T * const a, size_t n)
416
+ {
417
+ return pretty_print::array_wrapper_n<T>(a, n);
418
+ }
419
+
420
+ template <typename T> pretty_print::bucket_print_wrapper<T>
421
+ bucket_print(const T & m, typename T::size_type n)
422
+ {
423
+ return pretty_print::bucket_print_wrapper<T>(m, n);
424
+ }
425
+
426
+
427
+ // Main magic entry point: An overload snuck into namespace std.
428
+ // Can we do better?
429
+
430
+ namespace std
431
+ {
432
+ // Prints a container to the stream using default delimiters
433
+
434
+ template<typename T, typename TChar, typename TCharTraits>
435
+ inline typename enable_if< ::pretty_print::is_container<T>::value,
436
+ basic_ostream<TChar, TCharTraits> &>::type
437
+ operator<<(basic_ostream<TChar, TCharTraits> & stream, const T & container)
438
+ {
439
+ return stream << ::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
440
+ }
441
+ }
442
+
443
+
444
+
445
+ #endif // H_PRETTY_PRINT
@@ -0,0 +1,6 @@
1
+ require "cluster_eval/version"
2
+ require 'ClusterEval'
3
+
4
+ module ClusterEval
5
+
6
+ end
@@ -0,0 +1,3 @@
1
+ module ClusterEval
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'test_helper'
2
+ require 'cluster_eval'
3
+ #
4
+ # test tiny example
5
+ #
6
+ class TestConfusionMatrixSmall < MiniTest::Test
7
+ #
8
+ def setup
9
+ @h1= {0 => 0, 1 => 0, 2 => 1, 3 => 1, 4 => 1, 5 => 2, 6 => 2, 7 => 2}
10
+ @h2= {0 => 0, 1 => 1, 2 => 1, 3 => 1, 4 => 1, 5 => 1, 6 => 2, 7 => 2}
11
+ end
12
+ #
13
+ #
14
+ def test_small_confusion_matrix()
15
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
16
+ cm_ary = cm.get_confusion_matrix
17
+ assert_equal(4, cm_ary[0], 'Incorrect num for a')
18
+ assert_equal(3, cm_ary[1], 'Incorrect num for b')
19
+ assert_equal(7, cm_ary[2], 'Incorrect num for c')
20
+ assert_equal(14, cm_ary[3], 'Incorrect num for d')
21
+ #
22
+ cm_naive = cm.get_confusion_matrix_naive
23
+ assert_equal(cm_ary, cm_naive, 'confusion matrices do not agree')
24
+ end
25
+ #
26
+ #
27
+ def test_small_jaccard()
28
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
29
+ ji_val = cm.get_jaccard_index
30
+ assert_in_delta(0.28571, ji_val, 0.0001, 'incorrect Jaccard index')
31
+ end
32
+ #
33
+ #
34
+ def test_small_rand()
35
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
36
+ rand_val = cm.get_rand_index
37
+ assert_in_delta(0.64285, rand_val, 0.0001, 'incorrect Rand index')
38
+ end
39
+ #
40
+ #
41
+ def test_small_fm()
42
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
43
+ fm_val = cm.get_fm_index
44
+ assert_in_delta(0.45584, fm_val, 0.0001, 'incorrect FM index')
45
+ end
46
+ #
47
+ #
48
+ def test_small_rand_adj_rand()
49
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
50
+ rand_val = cm.get_adj_rand_index
51
+ assert_in_delta(0.2, rand_val, 0.0001, 'incorrect adjusted Rand index')
52
+ end
53
+
54
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'test_helper'
2
+ require 'cluster_eval'
3
+ #
4
+ # test two random (small) clusterings
5
+ #
6
+ class TestConfusionMatrixSmallRandom < MiniTest::Test
7
+ #
8
+ def setup
9
+ @h1 = {0 => 0, 1 => 1, 2 => 2, 3 => 0, 4 => 3, 5 => 4, 6 => 5, 7 => 1}
10
+ @h2 = {0 => 1, 1 => 1, 2 => 0, 3 => 0, 4 => 2, 5 => 2, 6 => 2, 7 => 2}
11
+ end
12
+ #
13
+ #
14
+ def test_small_rand_confusion_matrix()
15
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
16
+ cm_ary = cm.get_confusion_matrix
17
+ assert_equal(0, cm_ary[0], 'Incorrect num for a')
18
+ assert_equal(2, cm_ary[1], 'Incorrect num for b')
19
+ assert_equal(8, cm_ary[2], 'Incorrect num for c')
20
+ assert_equal(18, cm_ary[3], 'Incorrect num for d')
21
+ #
22
+ cm_naive = cm.get_confusion_matrix_naive
23
+ assert_equal(cm_ary, cm_naive, 'confusion matrices do not agree')
24
+ end
25
+ #
26
+ #
27
+ def test_small_rand_jaccard()
28
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
29
+ ji_val = cm.get_jaccard_index
30
+ assert_in_delta(0.000, ji_val, 0.0001, 'incorrect Jaccard index')
31
+ end
32
+ #
33
+ #
34
+ def test_small_rand_rand()
35
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
36
+ rand_val = cm.get_rand_index
37
+ assert_in_delta(0.64285, rand_val, 0.0001, 'incorrect Rand index')
38
+ end
39
+ #
40
+ #
41
+ def test_small_rand_fm()
42
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
43
+ fm_val = cm.get_fm_index
44
+ assert_in_delta(0.0000, fm_val, 0.0001, 'incorrect FM index')
45
+ end
46
+ #
47
+ #
48
+ def test_small_rand_adj_rand()
49
+ cm = ClusterEval::ConfusionMatrix.new(@h1,@h2)
50
+ rand_val = cm.get_adj_rand_index
51
+ assert_in_delta(-0.129032, rand_val, 0.0001, 'incorrect adjusted Rand index')
52
+ end
53
+
54
+ end
@@ -0,0 +1,17 @@
1
+ # minitest stuff
2
+ require 'rubygems'
3
+ gem 'minitest'
4
+ require 'minitest/autorun'
5
+
6
+ # minitest-reporters
7
+ require "minitest/reporters"
8
+ #Minitest::Reporters.use!
9
+ Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
10
+
11
+ def get_data_dir()
12
+ "#{File.dirname(__FILE__)}/data/"
13
+ end
14
+
15
+ ## if/when create a gem, remove this
16
+ $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib/")
17
+ $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../ext/")
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cluster_eval
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - sbonisso
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.19'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.19'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rice
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.4'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.4'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest-reporters
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ description: Evaluate partitionings of different clustering approaches. Provides different
98
+ metrics to use.
99
+ email:
100
+ - sbonisso@ucsd.edu
101
+ executables:
102
+ - cluster_eval
103
+ extensions:
104
+ - ext/extconf.rb
105
+ extra_rdoc_files: []
106
+ files:
107
+ - ".gitignore"
108
+ - ".travis.yml"
109
+ - Gemfile
110
+ - README.md
111
+ - Rakefile
112
+ - bin/cluster_eval
113
+ - bin/console
114
+ - bin/setup
115
+ - cluster_eval.gemspec
116
+ - ext/ConfusionMatrix.cpp
117
+ - ext/ConfusionMatrix.hpp
118
+ - ext/clusteval.cpp
119
+ - ext/extconf.rb
120
+ - ext/prettyprint.hpp
121
+ - lib/cluster_eval.rb
122
+ - lib/cluster_eval/version.rb
123
+ - tests/test_confusion_matrix_small.rb
124
+ - tests/test_confusion_matrix_small_random.rb
125
+ - tests/test_helper.rb
126
+ homepage: https://github.com/sbonisso/cluster_eval
127
+ licenses:
128
+ - MIT
129
+ metadata: {}
130
+ post_install_message:
131
+ rdoc_options: []
132
+ require_paths:
133
+ - lib
134
+ - ext
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.4.6
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Evaluation of clusterings
151
+ test_files: []
152
+ has_rdoc: