stable_match 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/Gemfile +1 -4
- data/README.md +46 -7
- data/Rakefile +35 -40
- data/examples/example_1.rb +12 -12
- data/lib/stable_match.rb +3 -6
- data/lib/stable_match/candidate.rb +74 -104
- data/lib/stable_match/runner.rb +81 -98
- data/lib/stable_match/test.rb +49 -0
- data/lib/stable_match/util.rb +1 -0
- data/lib/stable_match/util/initialize_with_defaults.rb +27 -0
- data/lib/stable_match/version.rb +1 -1
- data/stable_match.gemspec +7 -15
- data/test/functional/nrmp_test.rb +18 -16
- data/test/functional/stable_marriage_test.rb +75 -0
- data/test/test_helper.rb +22 -7
- data/test/unit/lib/stable_match/candidate_test.rb +3 -41
- data/test/unit/lib/stable_match/runner_test.rb +11 -34
- data/test/unit/lib/stable_match/util/intialize_with_defaults_test.rb +49 -0
- data/test/unit/lib/stable_match_test.rb +2 -2
- metadata +26 -56
- data/test/support/minitest.rb +0 -51
data/test/test_helper.rb
CHANGED
@@ -1,10 +1,25 @@
|
|
1
|
-
require
|
2
|
-
gem
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'minitest'
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'minitest/pride'
|
6
6
|
|
7
|
-
require
|
7
|
+
require 'stable_match/test'
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
BEGIN {
|
10
|
+
def __load_bundle_env!
|
11
|
+
is_blank = lambda { |o| o.nil? or o.size < 1 }
|
12
|
+
ENV[ 'BUNDLE_GEMFILE' ] = File.expand_path( 'Gemfile' ) if is_blank[ ENV[ 'BUNDLE_GEMFILE' ] ]
|
13
|
+
begin
|
14
|
+
require 'bundler'
|
15
|
+
rescue
|
16
|
+
require 'rubygems'
|
17
|
+
require 'bundler'
|
18
|
+
ensure
|
19
|
+
raise LoadError.new( 'Bundler not found!' ) unless defined?( Bundler )
|
20
|
+
require 'bundler/setup'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
__load_bundle_env! unless defined?( Bundler )
|
25
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require 'test_helper'
|
2
2
|
|
3
|
-
class StableMatch::
|
3
|
+
class StableMatch::CandidateTest < StableMatch::Test
|
4
4
|
def setup
|
5
5
|
@candidate1 = StableMatch::Candidate.new 1 , [ 2 , 3 ]
|
6
6
|
@candidate2 = StableMatch::Candidate.new 2 , [ 1 , 3 ]
|
@@ -11,32 +11,14 @@ class StableMatch::CandidateUnitTest < MiniTest::Unit::TestCase
|
|
11
11
|
@candidate3.preferences = [ @candidate2 , @candidate1 ]
|
12
12
|
end
|
13
13
|
|
14
|
-
## Candidate#initialize
|
15
|
-
#
|
16
|
-
def test_accepts_args_as_named_options_or_positionally
|
17
|
-
target = 1
|
18
|
-
preferences = 2
|
19
|
-
|
20
|
-
assert{ StableMatch::Candidate.new( target , preferences ) }
|
21
|
-
assert{ StableMatch::Candidate.new( :target => target , :preferences => preferences ) }
|
22
|
-
|
23
|
-
candidate = assert{ StableMatch::Candidate.new( target , :preferences => preferences ) }
|
24
|
-
assert{ candidate.target == target }
|
25
|
-
|
26
|
-
candidate = assert{ StableMatch::Candidate.new( preferences , :target => target ) }
|
27
|
-
assert{ candidate.preferences == preferences }
|
28
|
-
end
|
29
|
-
|
30
14
|
def test_match_positions_option_overrides_default
|
31
15
|
assert{ @candidate1.match_positions }
|
32
16
|
|
33
17
|
match_positions = 3
|
34
|
-
candidate = StableMatch::Candidate.new( 1 , [ 2 , 3 ] ,
|
18
|
+
candidate = StableMatch::Candidate.new( 1 , [ 2 , 3 ] , match_positions )
|
35
19
|
assert{ candidate.match_positions == match_positions }
|
36
20
|
end
|
37
21
|
|
38
|
-
## Candidate#better_match?
|
39
|
-
#
|
40
22
|
def test_better_match_returns_false_if_not_preferred
|
41
23
|
candidate4 = StableMatch::Candidate.new 4 , [ @candidate3 , @candidate2 ]
|
42
24
|
assert{ !@candidate1.better_match?( candidate4 ) }
|
@@ -56,8 +38,6 @@ class StableMatch::CandidateUnitTest < MiniTest::Unit::TestCase
|
|
56
38
|
assert{ @candidate1.better_match? @candidate2 }
|
57
39
|
end
|
58
40
|
|
59
|
-
## Candidate#exhausted_preferences?
|
60
|
-
#
|
61
41
|
def test_exhausted_preferences_returns_false_if_not_all_preferences_have_been_checked
|
62
42
|
assert{ !@candidate1.exhausted_preferences? }
|
63
43
|
end
|
@@ -67,8 +47,6 @@ class StableMatch::CandidateUnitTest < MiniTest::Unit::TestCase
|
|
67
47
|
assert{ @candidate1.exhausted_preferences? }
|
68
48
|
end
|
69
49
|
|
70
|
-
## Candidate#free?
|
71
|
-
#
|
72
50
|
def test_free_returns_false_if_all_match_positions_are_filled
|
73
51
|
@candidate1.match! @candidate2
|
74
52
|
assert{ !@candidate1.free? }
|
@@ -78,8 +56,6 @@ class StableMatch::CandidateUnitTest < MiniTest::Unit::TestCase
|
|
78
56
|
assert{ @candidate1.free? }
|
79
57
|
end
|
80
58
|
|
81
|
-
## Candidate#free!
|
82
|
-
#
|
83
59
|
def test_free_returns_false_if_there_are_no_matches
|
84
60
|
assert{ !@candidate1.free! }
|
85
61
|
end
|
@@ -96,8 +72,6 @@ class StableMatch::CandidateUnitTest < MiniTest::Unit::TestCase
|
|
96
72
|
assert{ !@candidate2.matches.include?( @candidate1 ) }
|
97
73
|
end
|
98
74
|
|
99
|
-
## Candidate#full?
|
100
|
-
#
|
101
75
|
def test_free_returns_false_if_all_match_positions_are_filled
|
102
76
|
@candidate1.match! @candidate2
|
103
77
|
assert{ @candidate1.full? }
|
@@ -107,8 +81,6 @@ class StableMatch::CandidateUnitTest < MiniTest::Unit::TestCase
|
|
107
81
|
assert{ !@candidate1.full? }
|
108
82
|
end
|
109
83
|
|
110
|
-
## Candidate#match!
|
111
|
-
#
|
112
84
|
def test_match_returns_false_if_other_is_not_preferred
|
113
85
|
candidate4 = StableMatch::Candidate.new 4 , [ @candidate3 , @candidate2 ]
|
114
86
|
assert{ !@candidate1.match!( candidate4 ) }
|
@@ -129,8 +101,6 @@ class StableMatch::CandidateUnitTest < MiniTest::Unit::TestCase
|
|
129
101
|
assert{ @candidate2.matches.include? @candidate1 }
|
130
102
|
end
|
131
103
|
|
132
|
-
## Candidate#matched?
|
133
|
-
#
|
134
104
|
def test_matched_returns_full_with_no_args
|
135
105
|
@candidate1.match! @candidate2
|
136
106
|
assert{ @candidate1.matched? == @candidate1.full? }
|
@@ -141,8 +111,6 @@ class StableMatch::CandidateUnitTest < MiniTest::Unit::TestCase
|
|
141
111
|
assert{ @candidate1.matched? @candidate2 }
|
142
112
|
end
|
143
113
|
|
144
|
-
## Candidate#next_preference!
|
145
|
-
#
|
146
114
|
def test_next_preference_increments_the_preference_position
|
147
115
|
preference_position = @candidate1.preference_position
|
148
116
|
assert{ @candidate1.next_preference! }
|
@@ -154,22 +122,16 @@ class StableMatch::CandidateUnitTest < MiniTest::Unit::TestCase
|
|
154
122
|
assert{ expected_candidate == @candidate1.next_preference! }
|
155
123
|
end
|
156
124
|
|
157
|
-
## Candidate#prefers?
|
158
|
-
#
|
159
125
|
def test_prefers_checks_for_existence_of_candidate_in_preferences
|
160
126
|
assert{ @candidate1.prefers? @candidate2 }
|
161
127
|
assert{ !@candidate1.prefers?( "bogus" ) }
|
162
128
|
end
|
163
129
|
|
164
|
-
## Candidate#propose_to
|
165
|
-
#
|
166
130
|
def test_propose_to_tracks_proposals
|
167
131
|
assert{ @candidate1.propose_to @candidate2 }
|
168
132
|
assert{ @candidate1.proposals.include? @candidate2 }
|
169
133
|
end
|
170
134
|
|
171
|
-
## Candidate#respond_to_proposal_from
|
172
|
-
#
|
173
135
|
def test_respond_to_proposal_from_returns_false_if_other_is_not_preferred
|
174
136
|
candidate4 = StableMatch::Candidate.new 4 , [ @candidate3 , @candidate2 ]
|
175
137
|
assert{ !@candidate1.respond_to_proposal_from( candidate4 ) }
|
@@ -1,34 +1,19 @@
|
|
1
|
-
require
|
1
|
+
require 'test_helper'
|
2
2
|
|
3
|
-
class StableMatch::
|
3
|
+
class StableMatch::RunnerTest < StableMatch::Test
|
4
4
|
def setup
|
5
|
-
@set1 = { 1 =>
|
6
|
-
@set2 = { 2 =>
|
5
|
+
@set1 = { 1 => [ 2 ] }
|
6
|
+
@set2 = { 2 => [ 1 ] }
|
7
7
|
end
|
8
8
|
|
9
|
-
## Runner::run
|
10
|
-
#
|
11
9
|
def test_has_a_factory_class_method_that_automatically_runs_match
|
12
10
|
runner = assert{ StableMatch::Runner.run @set1 , @set2 }
|
13
11
|
assert{ runner.checked? }
|
14
12
|
assert{ runner.built? }
|
15
13
|
end
|
16
14
|
|
17
|
-
## Runner#initialize
|
18
|
-
#
|
19
|
-
def test_accepts_args_as_named_options_or_positionally
|
20
|
-
assert{ StableMatch::Runner.new( @set1 , @set2 ) }
|
21
|
-
assert{ StableMatch::Runner.new( :set1 => @set1 , :set2 => @set2 ) }
|
22
|
-
|
23
|
-
runner = assert{ StableMatch::Runner.new( @set1 , :set2 => @set2 ) }
|
24
|
-
assert{ runner.set1 == @set1 }
|
25
|
-
|
26
|
-
runner = assert{ StableMatch::Runner.new( @set2 , :set1 => @set1 ) }
|
27
|
-
assert{ runner.set2 == @set2 }
|
28
|
-
end
|
29
|
-
|
30
15
|
def test_accepts_a_strategy_option
|
31
|
-
runner = assert{ StableMatch::Runner.new @set1 , @set2 , :
|
16
|
+
runner = assert{ StableMatch::Runner.new @set1 , @set2 , :asymmetric }
|
32
17
|
assert{ :asymmetric == runner.strategy }
|
33
18
|
end
|
34
19
|
|
@@ -36,8 +21,6 @@ class StableMatch::RunnerUnitTest < MiniTest::Unit::TestCase
|
|
36
21
|
assert{ StableMatch::Runner.new( @set1 , @set2 ).strategy == :symmetric }
|
37
22
|
end
|
38
23
|
|
39
|
-
## Runner#build!
|
40
|
-
#
|
41
24
|
def test_build_creates_candidate_sets_from_each_raw_set
|
42
25
|
runner = build_runner
|
43
26
|
assert{ runner.build! }
|
@@ -68,8 +51,6 @@ class StableMatch::RunnerUnitTest < MiniTest::Unit::TestCase
|
|
68
51
|
assert{ runner.built? }
|
69
52
|
end
|
70
53
|
|
71
|
-
## Runner#check!
|
72
|
-
#
|
73
54
|
def test_checks_that_sets_meet_criteria
|
74
55
|
runner = build_runner
|
75
56
|
assert{ runner.check! }
|
@@ -78,8 +59,8 @@ class StableMatch::RunnerUnitTest < MiniTest::Unit::TestCase
|
|
78
59
|
end
|
79
60
|
|
80
61
|
def test_checks_that_a_sets_preferences_are_included_in_other_set
|
81
|
-
set1 = { 1 =>
|
82
|
-
set2 = { 2 =>
|
62
|
+
set1 = { 1 => [ 2 ] }
|
63
|
+
set2 = { 2 => [ 1 , 3 ] }
|
83
64
|
runner = StableMatch::Runner.new set1 , set2
|
84
65
|
|
85
66
|
assert "set2 contains a preference for 3 that does not exist" do
|
@@ -93,8 +74,6 @@ class StableMatch::RunnerUnitTest < MiniTest::Unit::TestCase
|
|
93
74
|
end
|
94
75
|
end
|
95
76
|
|
96
|
-
## Runner#remaining_candidates
|
97
|
-
#
|
98
77
|
def test_remaining_candidates_rejects_candidates_that_have_filled_match_positions
|
99
78
|
runner = build_prepared_runner
|
100
79
|
original_size = runner.remaining_candidates.size
|
@@ -113,23 +92,21 @@ class StableMatch::RunnerUnitTest < MiniTest::Unit::TestCase
|
|
113
92
|
runner = build_prepared_runner
|
114
93
|
assert{ runner.strategy == :symmetric }
|
115
94
|
|
116
|
-
all
|
95
|
+
all = runner.candidates.map &:target
|
117
96
|
remaining = runner.remaining_candidates.map &:target
|
118
97
|
assert{ all.sort == remaining.sort }
|
119
98
|
|
120
|
-
runner.strategy :asymmetric
|
121
|
-
set1
|
99
|
+
runner.strategy = :asymmetric
|
100
|
+
set1 = @set1.keys
|
122
101
|
remaining = runner.remaining_candidates.map &:target
|
123
102
|
assert{ set1.sort == remaining.sort }
|
124
103
|
end
|
125
104
|
|
126
|
-
## Runner#run
|
127
|
-
#
|
128
105
|
def test_has_a_run_loop
|
129
106
|
assert{ build_runner.respond_to? :run }
|
130
107
|
end
|
131
108
|
|
132
|
-
private
|
109
|
+
private
|
133
110
|
|
134
111
|
def build_runner
|
135
112
|
assert{ StableMatch::Runner.new( @set1 , @set2 ) }
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class StableMatch::Util::InitializeWithDefaultsTest < StableMatch::Test
|
4
|
+
def test_can_be_included_in_a_class
|
5
|
+
assert do
|
6
|
+
Class.new do
|
7
|
+
include StableMatch::Util::InitializeWithDefaults
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_class_with_override_sets_defaults
|
13
|
+
klass =
|
14
|
+
assert do
|
15
|
+
Class.new do
|
16
|
+
include StableMatch::Util::InitializeWithDefaults
|
17
|
+
|
18
|
+
attr_accessor :wut
|
19
|
+
|
20
|
+
def initialize_defaults!
|
21
|
+
@wut ||= :wut
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
assert( 'default is set' ){ :wut == klass.new.wut }
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_class_still_respects_initialize
|
30
|
+
klass =
|
31
|
+
assert do
|
32
|
+
Class.new do
|
33
|
+
include StableMatch::Util::InitializeWithDefaults
|
34
|
+
|
35
|
+
attr_accessor :wut
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@wut = :initialized
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize_defaults!
|
42
|
+
@wut ||= :wut
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
assert( 'things get initialized' ){ :initialized == klass.new.wut }
|
48
|
+
end
|
49
|
+
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stable_match
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Ryan Cook
|
@@ -10,63 +9,36 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2014-01-16 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
|
-
- !ruby/object:Gem::Dependency
|
16
|
-
name: fattr
|
17
|
-
requirement: &70346750299680 !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
|
-
requirements:
|
20
|
-
- - ~>
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 2.2.1
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: *70346750299680
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: map
|
28
|
-
requirement: &70346750298320 !ruby/object:Gem::Requirement
|
29
|
-
none: false
|
30
|
-
requirements:
|
31
|
-
- - ~>
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 5.5.0
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: *70346750298320
|
37
14
|
- !ruby/object:Gem::Dependency
|
38
15
|
name: minitest
|
39
|
-
requirement:
|
40
|
-
none: false
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
41
17
|
requirements:
|
42
|
-
- -
|
18
|
+
- - ! '>='
|
43
19
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
20
|
+
version: '0'
|
45
21
|
type: :development
|
46
22
|
prerelease: false
|
47
|
-
version_requirements:
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ! '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
48
28
|
- !ruby/object:Gem::Dependency
|
49
29
|
name: rake
|
50
|
-
requirement:
|
51
|
-
none: false
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
52
31
|
requirements:
|
53
|
-
- -
|
32
|
+
- - ! '>='
|
54
33
|
- !ruby/object:Gem::Version
|
55
|
-
version: 0
|
34
|
+
version: '0'
|
56
35
|
type: :development
|
57
36
|
prerelease: false
|
58
|
-
version_requirements:
|
59
|
-
- !ruby/object:Gem::Dependency
|
60
|
-
name: rego
|
61
|
-
requirement: &70346750279080 !ruby/object:Gem::Requirement
|
62
|
-
none: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
38
|
requirements:
|
64
|
-
- -
|
39
|
+
- - ! '>='
|
65
40
|
- !ruby/object:Gem::Version
|
66
|
-
version:
|
67
|
-
type: :development
|
68
|
-
prerelease: false
|
69
|
-
version_requirements: *70346750279080
|
41
|
+
version: '0'
|
70
42
|
description: A generic implementation of the stable match algorightm.
|
71
43
|
email:
|
72
44
|
- cookrn@gmail.com
|
@@ -84,48 +56,46 @@ files:
|
|
84
56
|
- lib/stable_match.rb
|
85
57
|
- lib/stable_match/candidate.rb
|
86
58
|
- lib/stable_match/runner.rb
|
59
|
+
- lib/stable_match/test.rb
|
60
|
+
- lib/stable_match/util.rb
|
61
|
+
- lib/stable_match/util/initialize_with_defaults.rb
|
87
62
|
- lib/stable_match/version.rb
|
88
63
|
- stable_match.gemspec
|
89
64
|
- test/functional/nrmp_test.rb
|
90
|
-
- test/
|
65
|
+
- test/functional/stable_marriage_test.rb
|
91
66
|
- test/test_helper.rb
|
92
67
|
- test/unit/lib/stable_match/candidate_test.rb
|
93
68
|
- test/unit/lib/stable_match/runner_test.rb
|
69
|
+
- test/unit/lib/stable_match/util/intialize_with_defaults_test.rb
|
94
70
|
- test/unit/lib/stable_match_test.rb
|
95
71
|
homepage: https://github.com/cookrn/stable_match
|
96
72
|
licenses: []
|
73
|
+
metadata: {}
|
97
74
|
post_install_message:
|
98
75
|
rdoc_options: []
|
99
76
|
require_paths:
|
100
77
|
- lib
|
101
78
|
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
-
none: false
|
103
79
|
requirements:
|
104
80
|
- - ! '>='
|
105
81
|
- !ruby/object:Gem::Version
|
106
82
|
version: '0'
|
107
|
-
segments:
|
108
|
-
- 0
|
109
|
-
hash: 1686263240201859954
|
110
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
-
none: false
|
112
84
|
requirements:
|
113
85
|
- - ! '>='
|
114
86
|
- !ruby/object:Gem::Version
|
115
87
|
version: '0'
|
116
|
-
segments:
|
117
|
-
- 0
|
118
|
-
hash: 1686263240201859954
|
119
88
|
requirements: []
|
120
89
|
rubyforge_project:
|
121
|
-
rubygems_version:
|
90
|
+
rubygems_version: 2.0.4
|
122
91
|
signing_key:
|
123
|
-
specification_version:
|
92
|
+
specification_version: 4
|
124
93
|
summary: stable_match v0.1.0
|
125
94
|
test_files:
|
126
95
|
- test/functional/nrmp_test.rb
|
127
|
-
- test/
|
96
|
+
- test/functional/stable_marriage_test.rb
|
128
97
|
- test/test_helper.rb
|
129
98
|
- test/unit/lib/stable_match/candidate_test.rb
|
130
99
|
- test/unit/lib/stable_match/runner_test.rb
|
100
|
+
- test/unit/lib/stable_match/util/intialize_with_defaults_test.rb
|
131
101
|
- test/unit/lib/stable_match_test.rb
|