leap 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -89,12 +89,20 @@ class Person
89
89
  end
90
90
  end
91
91
  ```
92
+
93
+ ``` irb
94
+ > Person.new(:watch => Watch.new).time
95
+ => 3:02pm
96
+ ```
97
+
92
98
  The `decide :time do . . . end` block is called the *decision*. In this case, we're describing how to decide *time* for a given Person; we say that time is the *goal* of the decision. Leap will define a method on the object named after the decision (in this case, `Person#time`). Calling this method computes the decision.
93
99
 
94
- The `committee :time do . . . end` block is called a *committee*. Committees represent a set of methodologies, all of which are appropriate means of determining its namesake property, in this case *time*. All decision blocks must at the very least provide a committee for the goal; this is implicitly the *master committee*. Typically Leap decisions will involve many more committees, each of which is tasked with determining some intermediate result necessary for the master committee to arrive at a conclusion.
100
+ The `committee :time do . . . end` block is called a *committee*. Committees represent a set of methodologies, all of which are appropriate means of determining its namesake property, in this case *time*. Most decision blocks provide a committee named the same as the goal; this is implicitly the *master committee*. Typically Leap decisions will involve many more committees, each of which is tasked with determining some intermediate result necessary for the master committee to arrive at a conclusion.
95
101
 
96
102
  The `quorum 'look at your watch' . . . end` block is called a *quorum*. Quorums describe *one particular way* of reaching the committee's conclusion, along with a list (`:needs`) of what they need to be employed. The `characteristics` blockvar is a curated subset of the object's attributes presented to the quorum (which is in this sense a *closure*) for consideration.
97
103
 
104
+ The `Person#time` method, which is created dynamically by Leap, is called the *goal method*---it actually performs the decision on the object.
105
+
98
106
  Back to the example. Having a watch does indeed make telling time easy. Complexities arise when you don't; you have to fallback to more intuitive methods.
99
107
 
100
108
  For example, we can look at the angle of the sun. (I'm going to start abbreviating the code blocks at this point.)
@@ -133,7 +141,17 @@ end
133
141
 
134
142
  Surely there is more than one way of determining the Person's current address, so, as you can see, a dozen or more committees, each with several quorums, would be necessary to completely describe the intuitive process that we humans use to figure out something as simple as the likely time of day. This is a useful way to think about Leap: it's a non-learning artifical intelligence system that attempts to model human intuition by describing heuristic strategies.
135
143
 
136
- Now that we've looked at an overview of the Leap system, let's look at each component in depth, from the inside (characteristics) out (decisions).
144
+ Now that we've looked at an overview of the Leap system, let's look at each component in depth, starting with the goal method and proceeding from the inside (characteristics) out (decisions).
145
+
146
+ ## Goal method
147
+
148
+ Since Leap helps determine non-obvious attributes of objects, its decisions are made using methods that look and behave like attribute accessors:
149
+
150
+ ``` ruby
151
+ @person.time # Makes the "time" decision (as defined on Person) using @person's characteristics
152
+ ```
153
+
154
+ If there is a master commitee, the goal method returns its report; if not, it returns a hash of all the committees' reports.
137
155
 
138
156
  ## Characteristics
139
157
 
data/Rakefile CHANGED
@@ -25,16 +25,3 @@ Rake::TestTask.new(:test) do |test|
25
25
  test.verbose = true
26
26
  end
27
27
  task :default => :test
28
-
29
- begin
30
- require 'rake/rdoctask'
31
- Rake::RDocTask.new do |rdoc|
32
- rdoc.rdoc_dir = 'rdoc'
33
- rdoc.title = 'leap'
34
- rdoc.options << '--line-numbers' << '--inline-source'
35
- rdoc.rdoc_files.include('README*')
36
- rdoc.rdoc_files.include('lib/**/*.rb')
37
- end
38
- rescue LoadError
39
- puts "Rdoc is not available"
40
- end
@@ -1,28 +1,28 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "leap/version"
4
-
5
- Gem::Specification.new do |s|
6
- s.name = "leap"
7
- s.version = Leap::VERSION
8
- s.platform = Gem::Platform::RUBY
9
- s.authors = ["Andy Rossmeissl", "Seamus Abshere", "Derek Kastner"]
10
- s.email = "andy@rossmeissl.net"
11
- s.homepage = "http://github.com/rossmeissl/leap"
12
- s.summary = %Q{A heuristics engine for your Ruby objects}
13
- s.description = %Q{Leap to conclusions}
14
-
15
- s.files = `git ls-files`.split("\n")
16
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
- s.require_paths = ["lib"]
19
-
20
- s.add_development_dependency "charisma", '~>0.2.0'
21
- s.add_development_dependency "shoulda"
22
- s.add_development_dependency 'bueller'
23
- s.add_dependency 'blockenspiel', '>=0.3.2'
24
- s.add_dependency 'activesupport', '>=2.3.4'
25
- # sabshere 1/27/11 for activesupport - http://groups.google.com/group/ruby-bundler/browse_thread/thread/b4a2fc61ac0b5438
26
- s.add_dependency 'i18n'
27
- s.add_dependency 'builder'
28
- end
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "leap/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "leap"
7
+ s.version = Leap::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Andy Rossmeissl", "Seamus Abshere", "Derek Kastner"]
10
+ s.email = "andy@rossmeissl.net"
11
+ s.homepage = "http://github.com/rossmeissl/leap"
12
+ s.summary = %Q{A heuristics engine for your Ruby objects}
13
+ s.description = %Q{Leap to conclusions}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency "charisma", '~>0.2.0'
21
+ s.add_development_dependency "shoulda"
22
+ s.add_development_dependency 'bueller'
23
+ s.add_dependency 'blockenspiel', '>=0.3.2'
24
+ s.add_dependency 'activesupport', '>=2.3.4'
25
+ # sabshere 1/27/11 for activesupport - http://groups.google.com/group/ruby-bundler/browse_thread/thread/b4a2fc61ac0b5438
26
+ s.add_dependency 'i18n'
27
+ s.add_dependency 'builder'
28
+ end
@@ -23,6 +23,11 @@ module Leap
23
23
  @committees = []
24
24
  end
25
25
 
26
+ # Answers whether or not the decision has a "master committee"--a committee with the same name as the decision's goal.
27
+ def mastered?
28
+ !!committees.find { |committee| committee.name == goal }
29
+ end
30
+
26
31
  # Make the decision.
27
32
  #
28
33
  # General you won't call this directly, but rather use the dynamically-created method with this decision's goal as its name on the subject instance.
@@ -11,7 +11,7 @@ module Leap
11
11
  # @param [optional, Array] considerations An ordered array of additional details, immutable during the course of deliberation, that should be made available to each committee for provision, upon request, to quorums.
12
12
  # @param [optional, Hash] options Additional options
13
13
  # @option comply Force the ensuing deliberation to comply with one or more "protocols" by only respecting quorums that comply with this (these) protocol(s). Protocols can be anything--a Fixnum, a String, whatever, but by tradition a Symbol. If compliance is required with multiple protocols, they should be passed in an Array.
14
- # @return The value of the newly-decided goal.
14
+ # @return The value of the newly-decided goal--or, if there is no committee with the same name as the goal, a hash of committee reports
15
15
  # @raise [Leap::NoSolutionError] Leap could not compute the decision's goal on this subject instance given its characteristics and compliance constraint.
16
16
  def method_missing(*args, &blk)
17
17
  super
@@ -54,10 +54,13 @@ module Leap
54
54
  decision = self.class.decisions[goal]
55
55
  characteristics = send(self.class.decisions[goal].signature_method)
56
56
  @deliberations[goal] = decision.make(characteristics, *considerations)
57
- if @deliberations[goal][goal].nil?
57
+ if self.class.decisions[goal].mastered? and @deliberations[goal][goal].nil?
58
58
  raise ::Leap::NoSolutionError, :goal => goal, :deliberation => @deliberations[goal]
59
+ elsif self.class.decisions[goal].mastered?
60
+ @deliberations[goal][goal]
61
+ else
62
+ @deliberations[goal]
59
63
  end
60
- @deliberations[goal][goal]
61
64
  end
62
65
  end
63
66
  end
@@ -1,3 +1,3 @@
1
- module Leap
2
- VERSION = "0.5.4"
3
- end
1
+ module Leap
2
+ VERSION = "0.5.5"
3
+ end
@@ -119,3 +119,15 @@ class Seamus
119
119
  end
120
120
  end
121
121
  end
122
+
123
+ class Idea
124
+ include Leap
125
+ decide :value do
126
+ committee :cost do
127
+ quorum('default') {0}
128
+ end
129
+ committee :benefit do
130
+ quorum('default') {1}
131
+ end
132
+ end
133
+ end
@@ -157,4 +157,19 @@ class TestLeap < Test::Unit::TestCase
157
157
  assert_equal :length, Owl.decisions[:eye_size].committees.first.options[:measures]
158
158
  end
159
159
  end
160
+
161
+ context 'A decision without a master committee' do
162
+ setup do
163
+ @idea = Idea.new
164
+ end
165
+
166
+ should 'still compute' do
167
+ @idea.value
168
+ assert_equal({:cost => 0, :benefit => 1}, @idea.deliberations[:value].characteristics)
169
+ end
170
+
171
+ should 'provide easy access to committee reports' do
172
+ assert_equal 0, @idea.value[:cost]
173
+ end
174
+ end
160
175
  end
metadata CHANGED
@@ -1,8 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leap
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 1
4
5
  prerelease:
5
- version: 0.5.4
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 5
10
+ version: 0.5.5
6
11
  platform: ruby
7
12
  authors:
8
13
  - Andy Rossmeissl
@@ -12,86 +17,112 @@ autorequire:
12
17
  bindir: bin
13
18
  cert_chain: []
14
19
 
15
- date: 2011-06-02 00:00:00 -05:00
16
- default_executable:
20
+ date: 2011-08-17 00:00:00 Z
17
21
  dependencies:
18
22
  - !ruby/object:Gem::Dependency
19
23
  name: charisma
20
- requirement: &id001 !ruby/object:Gem::Requirement
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
21
25
  none: false
22
26
  requirements:
23
27
  - - ~>
24
28
  - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 0
32
+ - 2
33
+ - 0
25
34
  version: 0.2.0
26
- type: :development
27
35
  prerelease: false
28
- version_requirements: *id001
36
+ type: :development
37
+ requirement: *id001
29
38
  - !ruby/object:Gem::Dependency
30
39
  name: shoulda
31
- requirement: &id002 !ruby/object:Gem::Requirement
40
+ version_requirements: &id002 !ruby/object:Gem::Requirement
32
41
  none: false
33
42
  requirements:
34
43
  - - ">="
35
44
  - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
36
48
  version: "0"
37
- type: :development
38
49
  prerelease: false
39
- version_requirements: *id002
50
+ type: :development
51
+ requirement: *id002
40
52
  - !ruby/object:Gem::Dependency
41
53
  name: bueller
42
- requirement: &id003 !ruby/object:Gem::Requirement
54
+ version_requirements: &id003 !ruby/object:Gem::Requirement
43
55
  none: false
44
56
  requirements:
45
57
  - - ">="
46
58
  - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
47
62
  version: "0"
48
- type: :development
49
63
  prerelease: false
50
- version_requirements: *id003
64
+ type: :development
65
+ requirement: *id003
51
66
  - !ruby/object:Gem::Dependency
52
67
  name: blockenspiel
53
- requirement: &id004 !ruby/object:Gem::Requirement
68
+ version_requirements: &id004 !ruby/object:Gem::Requirement
54
69
  none: false
55
70
  requirements:
56
71
  - - ">="
57
72
  - !ruby/object:Gem::Version
73
+ hash: 23
74
+ segments:
75
+ - 0
76
+ - 3
77
+ - 2
58
78
  version: 0.3.2
59
- type: :runtime
60
79
  prerelease: false
61
- version_requirements: *id004
80
+ type: :runtime
81
+ requirement: *id004
62
82
  - !ruby/object:Gem::Dependency
63
83
  name: activesupport
64
- requirement: &id005 !ruby/object:Gem::Requirement
84
+ version_requirements: &id005 !ruby/object:Gem::Requirement
65
85
  none: false
66
86
  requirements:
67
87
  - - ">="
68
88
  - !ruby/object:Gem::Version
89
+ hash: 11
90
+ segments:
91
+ - 2
92
+ - 3
93
+ - 4
69
94
  version: 2.3.4
70
- type: :runtime
71
95
  prerelease: false
72
- version_requirements: *id005
96
+ type: :runtime
97
+ requirement: *id005
73
98
  - !ruby/object:Gem::Dependency
74
99
  name: i18n
75
- requirement: &id006 !ruby/object:Gem::Requirement
100
+ version_requirements: &id006 !ruby/object:Gem::Requirement
76
101
  none: false
77
102
  requirements:
78
103
  - - ">="
79
104
  - !ruby/object:Gem::Version
105
+ hash: 3
106
+ segments:
107
+ - 0
80
108
  version: "0"
81
- type: :runtime
82
109
  prerelease: false
83
- version_requirements: *id006
110
+ type: :runtime
111
+ requirement: *id006
84
112
  - !ruby/object:Gem::Dependency
85
113
  name: builder
86
- requirement: &id007 !ruby/object:Gem::Requirement
114
+ version_requirements: &id007 !ruby/object:Gem::Requirement
87
115
  none: false
88
116
  requirements:
89
117
  - - ">="
90
118
  - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
91
122
  version: "0"
92
- type: :runtime
93
123
  prerelease: false
94
- version_requirements: *id007
124
+ type: :runtime
125
+ requirement: *id007
95
126
  description: Leap to conclusions
96
127
  email: andy@rossmeissl.net
97
128
  executables: []
@@ -104,7 +135,6 @@ files:
104
135
  - .document
105
136
  - .gitignore
106
137
  - Gemfile
107
- - LICENSE
108
138
  - README.markdown
109
139
  - Rakefile
110
140
  - leap.gemspec
@@ -123,7 +153,6 @@ files:
123
153
  - lib/leap/version.rb
124
154
  - test/helper.rb
125
155
  - test/test_leap.rb
126
- has_rdoc: true
127
156
  homepage: http://github.com/rossmeissl/leap
128
157
  licenses: []
129
158
 
@@ -137,7 +166,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
166
  requirements:
138
167
  - - ">="
139
168
  - !ruby/object:Gem::Version
140
- hash: -1210512428885299124
169
+ hash: 3
141
170
  segments:
142
171
  - 0
143
172
  version: "0"
@@ -146,17 +175,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
175
  requirements:
147
176
  - - ">="
148
177
  - !ruby/object:Gem::Version
149
- hash: -1210512428885299124
178
+ hash: 3
150
179
  segments:
151
180
  - 0
152
181
  version: "0"
153
182
  requirements: []
154
183
 
155
184
  rubyforge_project:
156
- rubygems_version: 1.6.2
185
+ rubygems_version: 1.8.8
157
186
  signing_key:
158
187
  specification_version: 3
159
188
  summary: A heuristics engine for your Ruby objects
160
- test_files:
161
- - test/helper.rb
162
- - test/test_leap.rb
189
+ test_files: []
190
+
data/LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright (c) 2009 Andy Rossmeissl
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.