leap 0.5.4 → 0.5.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +20 -2
- data/Rakefile +0 -13
- data/leap.gemspec +28 -28
- data/lib/leap/decision.rb +5 -0
- data/lib/leap/goal_methods_documentation.rb +1 -1
- data/lib/leap/subject.rb +5 -2
- data/lib/leap/version.rb +3 -3
- data/test/helper.rb +12 -0
- data/test/test_leap.rb +15 -0
- metadata +60 -32
- data/LICENSE +0 -20
data/README.markdown
CHANGED
@@ -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*.
|
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
|
data/leap.gemspec
CHANGED
@@ -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
|
data/lib/leap/decision.rb
CHANGED
@@ -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
|
data/lib/leap/subject.rb
CHANGED
@@ -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
|
data/lib/leap/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Leap
|
2
|
-
VERSION = "0.5.
|
3
|
-
end
|
1
|
+
module Leap
|
2
|
+
VERSION = "0.5.5"
|
3
|
+
end
|
data/test/helper.rb
CHANGED
data/test/test_leap.rb
CHANGED
@@ -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
|
-
|
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-
|
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
|
-
|
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
|
-
|
36
|
+
type: :development
|
37
|
+
requirement: *id001
|
29
38
|
- !ruby/object:Gem::Dependency
|
30
39
|
name: shoulda
|
31
|
-
|
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
|
-
|
50
|
+
type: :development
|
51
|
+
requirement: *id002
|
40
52
|
- !ruby/object:Gem::Dependency
|
41
53
|
name: bueller
|
42
|
-
|
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
|
-
|
64
|
+
type: :development
|
65
|
+
requirement: *id003
|
51
66
|
- !ruby/object:Gem::Dependency
|
52
67
|
name: blockenspiel
|
53
|
-
|
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
|
-
|
80
|
+
type: :runtime
|
81
|
+
requirement: *id004
|
62
82
|
- !ruby/object:Gem::Dependency
|
63
83
|
name: activesupport
|
64
|
-
|
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
|
-
|
96
|
+
type: :runtime
|
97
|
+
requirement: *id005
|
73
98
|
- !ruby/object:Gem::Dependency
|
74
99
|
name: i18n
|
75
|
-
|
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
|
-
|
110
|
+
type: :runtime
|
111
|
+
requirement: *id006
|
84
112
|
- !ruby/object:Gem::Dependency
|
85
113
|
name: builder
|
86
|
-
|
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
|
-
|
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:
|
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:
|
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.
|
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
|
-
|
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.
|