metric_space 0.0.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: c7441e2c577b880b3d511bdd2e726fb1082d111f
4
+ data.tar.gz: 5897051193d86ae84a6b00ad7c3c742bf660bb06
5
+ SHA512:
6
+ metadata.gz: ec725f1af4b59acc0ad656800aff00526c3de08ab4104a6a7266320e4fdcda9d8bb511e44ba745b0d1d96a9d514dc02bbec47675b5efe056317a3fb93920ff19
7
+ data.tar.gz: 0e8599bcc362dbc17eb91f6c8e9fdb892485f350ae2530b0ed41a667e23ba51397488c7bec944219a3075abceb049bc4da2c88b9f8390fdc397e35318ebdea99
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ metric_space
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## v0.0.1
2
+
3
+ * initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in metric_space.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ guard 'bundler' do
2
+ watch('Gemfile')
3
+ watch(/^.+\.gemspec/)
4
+ end
5
+
6
+ guard :rspec do
7
+ watch(%r{^spec/.+_spec\.rb$})
8
+ watch(%r{^lib/(.+)\.rb$}) do |array|
9
+ name = array.last
10
+ "spec/#{name}_spec.rb"
11
+ end
12
+ watch('spec/spec_helper.rb') { "spec" }
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Fractal Soft
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # MetricSpace
2
+
3
+ Count distance between points in selected metric space
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'metric_space'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install metric_space
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc 'Default: run specs.'
5
+ task default: :spec
6
+
7
+ desc "Run specs"
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.rspec_opts = "--tag fast"
10
+ end
@@ -0,0 +1,35 @@
1
+ module MetricSpace
2
+ # The British Rail metric (also called the Post Office metric or
3
+ # the SNCF metric).
4
+ class BritishRail
5
+ # Distance between two points in British Rail metrics
6
+ #
7
+ # point1 = {a:2.5, b:5.0, c:1.0}
8
+ # point2 = {a:-1.5, b:1.5, c:0.5}
9
+ # self.distance(point1, point2) #=> 7.85835781757061
10
+ #
11
+ # point1 = {b:1.0, c:2.5, d:5.0}
12
+ # point2 = {a:-1.5, b:3.0, c:-1.5}
13
+ # self.distance(point1, point2) #=> 9.353142959975042
14
+ def self.distance(one, two)
15
+ first, second = self.normalize(one), self.normalize(two)
16
+ if first == second
17
+ Euclidean.distance(one, two)
18
+ else
19
+ Euclidean.distance(one, {}) + Euclidean.distance(two, {})
20
+ end
21
+ end
22
+
23
+ # Normalize point (all coefficients scaled to the largest one)
24
+ #
25
+ # self.normalize({a:2.0, b:1.0, c:0.5}) #=> {a:1.0, b:0.5, c:0.25}
26
+ # self.normalize({a:-2.0, b:4.0, c:-1.0}) #=> {a:-0.5, b:1.0, c:-0.25}
27
+ def self.normalize(point)
28
+ hash, max = point.dup, point.values.map(&:abs).max
29
+ hash.each_pair do |index, value|
30
+ hash[index] = value/max
31
+ end
32
+ hash
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ module MetricSpace
2
+ # Euclidean distance or Euclidean metric is the "ordinary" distance
3
+ # between two points that one would measure with a ruler,
4
+ # and is given by the Pythagorean formula.
5
+ class Euclidean < Metric
6
+ # Distance between two points in Euclidean metrics
7
+ #
8
+ # point1 = {a: 2.5, b: 5.0, c: 1.0}
9
+ # point2 = {a:-1.5, b: 1.5, c: 0.5}
10
+ # self.distance(point1, point2) #=> 5.338539126015656
11
+ #
12
+ # point1 = {b: 1.0, c: 2.5, d: 5.0}
13
+ # point2 = {a:-1.5, b: 3.0, c:-1.5}
14
+ # self.distance(point1, point2) #=> 6.87386354243376
15
+ def self.distance(one, two)
16
+ array, result = (one.keys + two.keys).uniq, 0.0
17
+ array.each do |index|
18
+ result += difference(one, two, index)**2
19
+ end
20
+ Math.sqrt(result)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module MetricSpace
2
+ # Maximum metric, Chebyshev distance, also known as chessboard distance,
3
+ # since in the game of chess the minimum number of moves needed by a king
4
+ # to go from one square on a chessboard to another equals the Chebyshev
5
+ # distance between the centers of the squares
6
+ class Maximum < Metric
7
+ # Distance between two points in Maximum (Chebyshev) metrics
8
+ #
9
+ # self.distance({a:2.5, b:5.0, c:1.0}, {a:-1.5, b:1.5, c:0.5}) #=> 4.0
10
+ # self.distance({a:-1.5, b:3.0, c:-1.5}, {b:1.0, c:2.5, d:5.0}) #=> 5.0
11
+ def self.distance(one, two)
12
+ array, max = (one.keys + two.keys).uniq, 0.0
13
+ array.each do |index|
14
+ value = difference(one, two, index)
15
+ max = value if value > max
16
+ end
17
+ max
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ module MetricSpace
2
+ # Difference between two values in one dimension
3
+ class Metric
4
+ protected
5
+ # Count difference between two points in selected dimension
6
+ def self.difference(one, two, index)
7
+ ((one[index] || 0.0) - (two[index] || 0.0)).abs
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ module MetricSpace
2
+ # The name relates to the distance a taxi has to drive in a rectangular street
3
+ # grid to get from the origin to the point x.
4
+ class Taxicab
5
+ # Distance between two points in taxicab metrics
6
+ #
7
+ # self.distance({a:2.5, b:5.0, c:1.0 }, {a:-1.5, b:1.5, c:0.5}) #=> 8.0
8
+ # self.distance({b:0.3, c:0.5, d:0.2 }, {a:-0.5, b:0.4, c:-0.4}) #=> 3.0
9
+ def self.distance(one, two)
10
+ array, result = (one.keys + two.keys).uniq, 0.0
11
+ array.each do |item|
12
+ result += (
13
+ (one.has_key?(item) ? one[item] : 0.0) -
14
+ (two.has_key?(item) ? two[item] : 0.0)
15
+ ).abs
16
+ end
17
+ result
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module MetricSpace
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,9 @@
1
+ require "metric_space/metric"
2
+ require "metric_space/british_rail"
3
+ require "metric_space/euclidean"
4
+ require "metric_space/maximum"
5
+ require "metric_space/taxicab"
6
+ require "metric_space/version"
7
+
8
+ module MetricSpace
9
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'metric_space/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "metric_space"
8
+ spec.version = MetricSpace::VERSION
9
+ spec.authors = ["Aleksander Malaszkiewicz"]
10
+ spec.email = ["info@fractalsoft.org"]
11
+ spec.summary = %q{Count distance between points in selected metric space}
12
+ spec.homepage = "https://github.com/fractalsoft/metric_space"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "guard"
24
+ spec.add_development_dependency "guard-bundler"
25
+ spec.add_development_dependency "guard-rspec"
26
+ end
@@ -0,0 +1,51 @@
1
+ require "spec_helper"
2
+
3
+ describe MetricSpace::BritishRail do
4
+ let(:klass) { MetricSpace::BritishRail }
5
+
6
+ describe ".distance" do
7
+ [
8
+ {
9
+ point1: {a: 3.0, b: 4.0},
10
+ point2: {a: 8.0, b: 6.0},
11
+ distance: 15.0
12
+ },
13
+ {
14
+ point1: {a: 3.0, c: 4.0},
15
+ point2: {a: 8.0, b: 6.0},
16
+ distance: 15.0
17
+ },
18
+ {
19
+ point1: {a: 4.0, b: 3.0},
20
+ point2: {a: 8.0, b: 6.0},
21
+ distance: 5.0
22
+ },
23
+ {
24
+ point1: {a: 4.0, b: -3.0},
25
+ point2: {a: -8.0, b: 6.0},
26
+ distance: 15.0
27
+ },
28
+ {
29
+ point1: {a: -1.5, b: 1.5},
30
+ point2: {a: 1.5, b: -1.5},
31
+ distance: 3*(2.0**0.5)
32
+ },
33
+ ].each do |example|
34
+ point1, point2, distance = example.values
35
+ it "should return #{distance} for distance between #{point1} and #{point2}" do
36
+ klass.distance(point1, point2).round(5).should eq(distance.round(5))
37
+ end
38
+ end
39
+ end
40
+
41
+ describe ".normalize" do
42
+ {
43
+ {a:2.0, b:1.0, c:0.5} => {a:1.0, b:0.5, c:0.25},
44
+ {a:-2.0, b:4.0, c:-1.0} => {a:-0.5, b:1.0, c:-0.25}
45
+ }.each_pair do |input, output|
46
+ it "should return #{output} for #{input}" do
47
+ klass.normalize({a:2.0, b:1.0, c:0.5}).should eq({a:1.0, b:0.5, c:0.25})
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+
3
+ describe MetricSpace::Euclidean do
4
+ let(:klass) { MetricSpace::Euclidean }
5
+ [
6
+ {
7
+ point1: {a: 7.25, b: 8.5},
8
+ point2: {a: 4.25, b: 4.5},
9
+ distance: 5.0
10
+ },
11
+ {
12
+ point1: {a: 0.5, c: 0.5},
13
+ point2: {b: 0.4, c: 0.8},
14
+ distance: 0.5**0.5
15
+ }
16
+ ].each do |example|
17
+ point1, point2, distance = example.values
18
+ it "should return #{distance} for distance between #{point1} and #{point2}" do
19
+ klass.distance(point1, point2).round(5).should eq(distance.round(5))
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+
3
+ describe MetricSpace::Maximum do
4
+ let(:klass) { MetricSpace::Maximum }
5
+ [
6
+ {
7
+ point1: {a: 7.25, b: 8.5, c: 2.0},
8
+ point2: {a: 4.25, b: 4.5, c: 7.0},
9
+ distance: 5
10
+ },
11
+ {
12
+ point1: {a: 0.3, c: 0.5},
13
+ point2: {b: 0.8, c: 0.9},
14
+ distance: 0.8
15
+ }
16
+ ].each do |example|
17
+ point1, point2, distance = example.values
18
+ it "should return #{distance} for distance between #{point1} and #{point2}" do
19
+ klass.distance(point1, point2).round(5).should eq(distance)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+
3
+ describe MetricSpace::Taxicab do
4
+ let(:klass) { MetricSpace::Taxicab }
5
+ [
6
+ {
7
+ point1: {a: -0.25, b: 3.25, c: 0.8},
8
+ point2: {a: 0.8, b: 1.25, c: 0.5},
9
+ distance: 3.35
10
+ },
11
+ {
12
+ point1: {a: 0.8, c: 0.5},
13
+ point2: {b: 0.3, c: 1},
14
+ distance: 1.6
15
+ }
16
+ ].each do |example|
17
+ point1, point2, distance = example.values
18
+ it "should return #{distance} for distance between #{point1} and #{point2}" do
19
+ klass.distance(point1, point2).round(5).should eq(distance)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ require 'metric_space'
8
+
9
+ RSpec.configure do |config|
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run :focus
13
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metric_space
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Aleksander Malaszkiewicz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description:
98
+ email:
99
+ - info@fractalsoft.org
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - .rspec
106
+ - .ruby-gemset
107
+ - .ruby-version
108
+ - .travis.yml
109
+ - CHANGELOG.md
110
+ - Gemfile
111
+ - Guardfile
112
+ - LICENSE.txt
113
+ - README.md
114
+ - Rakefile
115
+ - lib/metric_space.rb
116
+ - lib/metric_space/british_rail.rb
117
+ - lib/metric_space/euclidean.rb
118
+ - lib/metric_space/maximum.rb
119
+ - lib/metric_space/metric.rb
120
+ - lib/metric_space/taxicab.rb
121
+ - lib/metric_space/version.rb
122
+ - metric_space.gemspec
123
+ - spec/metric_space/british_rail_spec.rb
124
+ - spec/metric_space/euclidean_spec.rb
125
+ - spec/metric_space/maximum_spec.rb
126
+ - spec/metric_space/taxicab_spec.rb
127
+ - spec/spec_helper.rb
128
+ homepage: https://github.com/fractalsoft/metric_space
129
+ licenses:
130
+ - MIT
131
+ metadata: {}
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubyforge_project:
148
+ rubygems_version: 2.0.3
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: Count distance between points in selected metric space
152
+ test_files:
153
+ - spec/metric_space/british_rail_spec.rb
154
+ - spec/metric_space/euclidean_spec.rb
155
+ - spec/metric_space/maximum_spec.rb
156
+ - spec/metric_space/taxicab_spec.rb
157
+ - spec/spec_helper.rb