pius-rdfs 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/AUTHORS ADDED
@@ -0,0 +1,2 @@
1
+ * Arto Bendiken <arto.bendiken@gmail.com> (Lead developer)
2
+ * Pius Uzamere <pius@alum.mit.edu>
data/README ADDED
@@ -0,0 +1,84 @@
1
+ RDFS.rb: RDF Schema Reasoner for Ruby
2
+ =====================================
3
+
4
+ This is a pure-Ruby forward-chaining inference engine supporting RDFS
5
+ and RDFS++ entailment rules. It is intended to be used together with the
6
+ [RDF.rb](http://rdf.rubyforge.org/) library.
7
+
8
+ ### About RDF Schema (RDFS)
9
+
10
+ * <http://www.w3.org/TR/rdf-schema/>
11
+ * <http://www.w3.org/TR/rdf-mt/>
12
+ * <http://en.wikipedia.org/wiki/RDF_Schema>
13
+
14
+ Examples
15
+ --------
16
+
17
+ require 'rdfs'
18
+
19
+ ### Defining an RDFS entailment rule class
20
+
21
+ # @see http://www.w3.org/TR/rdf-mt/#RDFRules
22
+ class RDF1 < RDFS::Rule
23
+ antecedent :uuu, :aaa, :yyy
24
+ consequent :aaa, RDF.type, RDF.Property
25
+ end
26
+
27
+ ### Defining an RDFS entailment rule instance
28
+
29
+ # @see http://www.w3.org/TR/rdf-mt/#RDFRules
30
+ rdf1 = RDFS::Rule.new do
31
+ antecedent :uuu, :aaa, :yyy
32
+ consequent :aaa, RDF.type, RDF.Property
33
+ end
34
+
35
+ Documentation
36
+ -------------
37
+
38
+ * <http://rdfs.rubyforge.org/>
39
+
40
+ Download
41
+ --------
42
+
43
+ To get a local working copy of the development repository, do:
44
+
45
+ % git clone git://github.com/bendiken/rdfs.git
46
+
47
+ Alternatively, you can download the latest development version as a tarball
48
+ as follows:
49
+
50
+ % wget http://github.com/bendiken/rdfs/tarball/master
51
+
52
+ Dependencies
53
+ ------------
54
+
55
+ * [RDF.rb](http://rdf.rubyforge.org/) (>= 0.0.5)
56
+
57
+ Installation
58
+ ------------
59
+
60
+ The recommended installation method is via RubyGems. To install the latest
61
+ official release from Gemcutter, do:
62
+
63
+ % [sudo] gem install rdfs
64
+
65
+ Resources
66
+ ---------
67
+
68
+ * <http://rdfs.rubyforge.org/>
69
+ * <http://github.com/bendiken/rdfs>
70
+ * <http://gemcutter.org/gems/rdfs>
71
+ * <http://rubyforge.org/projects/rdfs/>
72
+ * <http://raa.ruby-lang.org/project/rdfs/>
73
+
74
+ Authors
75
+ ------
76
+
77
+ * [Arto Bendiken](mailto:arto.bendiken@gmail.com) - <http://ar.to/>
78
+ * [Pius Uzamere](mailto:pius@alum.mit.edu) - <http://pius.me/>
79
+
80
+ License
81
+ -------
82
+
83
+ RDFS.rb is free and unencumbered public domain software. For more
84
+ information, see <http://unlicense.org/> or the accompanying UNLICENSE file.
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
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 NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org/>
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'rdf'
3
+ require 'rdfs/version'
4
+ # require 'lib/rdfs/semantics'
5
+ # require 'lib/rdfs/rule'
6
+ # require 'lib/rdfs/repository'
7
+
8
+ ##
9
+ # RDF Schema (RDFS) support.
10
+ #
11
+ # @see http://www.w3.org/TR/rdf-schema/
12
+ module RDFS
13
+ include RDF
14
+
15
+ autoload :Reasoner, 'rdfs/reasoner'
16
+ autoload :Repository, 'rdfs/repository'
17
+ autoload :Rule, 'rdfs/rule'
18
+ autoload :Semantics, 'rdfs/semantics'
19
+
20
+ ##
21
+ # @return [#to_s] property
22
+ # @return [URI]
23
+ def self.[](property)
24
+ ::RDF::RDFS[property]
25
+ end
26
+
27
+ ##
28
+ # @param [Symbol] property
29
+ # @return [URI]
30
+ # @raise [NoMethodError]
31
+ def self.method_missing(property, *args, &block)
32
+ if args.empty?
33
+ ::RDF::RDFS[property]
34
+ else
35
+ super
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,7 @@
1
+ module RDFS
2
+ ##
3
+ # A rule-based forward-chaining RDFS inference engine.
4
+ class Reasoner
5
+ # TODO
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module RDFS
2
+ ##
3
+ # An RDF repository with RDFS entailment rules.
4
+ class Repository < RDF::Repository
5
+ include RDFS::Semantics
6
+ end
7
+ end
@@ -0,0 +1,197 @@
1
+ module RDF
2
+ class Statement
3
+ PLACEHOLDERS = (p = [:aaa, :bbb, :ccc, :ddd, :uuu, :vvv, :xxx, :yyy, :zzz]) + p.collect {|pl| RDF::Literal.new(pl)} + p.collect {|pl| RDF::Node.new(pl)}
4
+
5
+ #TODO: consider moving these methods into the RDF gem instead of reopening RDF::Statement here
6
+ def with_substitutions(assignment_hash)
7
+ return self unless assignment_hash
8
+ statement_hash = to_hash
9
+ [:subject, :object, :predicate].each { |place_in_statement|
10
+ bound_variables, variable = assignment_hash.keys, statement_hash[place_in_statement]
11
+ statement_hash[place_in_statement] = assignment_hash[variable] if bound_variables.collect(&:to_s).include?(variable.to_s)
12
+ #TODO: fix node equality so I don't need to use to_s above
13
+ }
14
+ Statement.new(statement_hash)
15
+ end
16
+
17
+ def generality
18
+ to_hash.values.select {|k| PLACEHOLDERS.include? k}.size
19
+ end
20
+
21
+ def has_placeholder?
22
+ to_hash.values.detect {|k| PLACEHOLDERS.include? k}
23
+ end
24
+
25
+ def specificity
26
+ 3-generality
27
+ end
28
+ end
29
+ end
30
+
31
+ module RDFS
32
+ ##
33
+ # An RDFS entailment rule.
34
+ class Rule
35
+ include RDF
36
+
37
+ PLACEHOLDERS = (p = [:aaa, :bbb, :ccc, :ddd, :uuu, :vvv, :xxx, :yyy, :zzz]) + p.collect {|pl| RDF::Literal.new(pl)} + p.collect {|pl| RDF::Node.new(pl)}
38
+
39
+ # @return [Array<Statement>]
40
+ attr_reader :antecedents
41
+
42
+ # @return [Hash{Symbol => Class}]
43
+ attr_reader :constraints
44
+
45
+ # @return [Array<Statement>]
46
+ attr_reader :consequents
47
+
48
+ ##
49
+ # @option options [Array<Statement>] :antecedents ([])
50
+ # @option options [Hash{Symbol => Class}] :constraints ({})
51
+ # @option options [Array<Statement>] :consequents ([])
52
+ # @yield [rule]
53
+ # @yieldparam [Rule]
54
+ def initialize(options = {}, &block)
55
+ @antecedents = (@@antecedents[self.class] || []).concat(options[:antecedents] || [])
56
+ @constraints = (@@constraints[self.class] || {}).merge( options[:constraints] || {})
57
+ @consequents = (@@consequents[self.class] || []).concat(options[:consequents] || [])
58
+
59
+ if block_given?
60
+ case block.arity
61
+ when 1 then block.call(self)
62
+ else instance_eval(&block)
63
+ end
64
+ end
65
+ end
66
+
67
+
68
+ def match(statement1, statement2=nil, noisy = false)
69
+ statements = [statement1, statement2].compact
70
+
71
+ return false unless antecedents.size == statements.size
72
+ if antecedents.size == 1
73
+ return false unless (@subs = self.class.unitary_match(antecedents.first, statements.first))
74
+ return Rule.substitute(consequents, @subs)
75
+
76
+ elsif (implied_assignments = Rule.unitary_match(antecedents_ordered_by_decreasing_specificity.first, statements.first))
77
+ q = Rule.unitary_match(antecedents_ordered_by_decreasing_specificity.last.with_substitutions(implied_assignments),
78
+ statements.last.with_substitutions(implied_assignments))
79
+ assignments = q ? q.merge(implied_assignments) : q
80
+ return Rule.substitute(consequents, assignments)
81
+ elsif implied_assignments = Rule.unitary_match(antecedents_ordered_by_decreasing_specificity.first, statements.last)
82
+ q = Rule.unitary_match(antecedents_ordered_by_decreasing_specificity.last.with_substitutions(implied_assignments),
83
+ statements.first.with_substitutions(implied_assignments))
84
+ assignments = q ? q.merge(implied_assignments) : q
85
+ return Rule.substitute(consequents, assignments)
86
+ else
87
+ return false
88
+ end
89
+ end
90
+ alias_method :[], :match
91
+
92
+
93
+ #returns either false or the assignment hash of the match
94
+ def self.unitary_match(antecedent, statement)
95
+ a, s = antecedent.to_hash, statement.to_hash
96
+ #may need to exclude context
97
+ bound = {}
98
+ a.values.zip(s.values) {|antecedent_value, statement_value|
99
+ if PLACEHOLDERS.include?(antecedent_value) and !bound[antecedent_value]
100
+ bound[antecedent_value] = statement_value
101
+ elsif PLACEHOLDERS.include?(antecedent_value) and bound[antecedent_value]
102
+ return false unless bound[antecedent_value] == statement_value
103
+ else
104
+ return false unless antecedent_value == statement_value
105
+ end
106
+ }
107
+ return bound
108
+ end
109
+
110
+ def antecedents_ordered_by_decreasing_specificity
111
+ a ||= antecedents.sort_by(&:generality)
112
+ end
113
+
114
+ def self.substitute(consequents, assignment_hash)
115
+ return nil if assignment_hash.nil?
116
+ c = consequents.collect{|c| c.with_substitutions(assignment_hash)}
117
+ return c.detect(&:has_placeholder?) ? false : c
118
+
119
+ #perhaps add an integrity check to Rule to make sure that the consequents are fully substituted by the antecedents
120
+ end
121
+
122
+ ##
123
+ # Defines an antecedent for this rule.
124
+ #
125
+ # @param [Symbol, URI] s
126
+ # @param [Symbol, URI] p
127
+ # @param [Symbol, URI] o
128
+ # @return [void]
129
+ def antecedent(s, p, o)
130
+ @antecedents << RDF::Statement.new(s, p, o)
131
+ end
132
+
133
+ ##
134
+ # Defines a type constraint for this rule.
135
+ #
136
+ # @param [Hash{Symbol => Class}] types
137
+ # @return [void]
138
+ def constraint(types = {})
139
+ @constraints.merge!(types)
140
+ end
141
+
142
+ ##
143
+ # Defines the consequent of this rule.
144
+ #
145
+ # @param [Symbol, URI] s
146
+ # @param [Symbol, URI] p
147
+ # @param [Symbol, URI] o
148
+ # @return [void]
149
+ def consequent(s, p, o)
150
+ @consequents << RDF::Statement.new(s, p, o)
151
+ end
152
+
153
+ protected
154
+ @@antecedents = {} # @private
155
+ @@constraints = {} # @private
156
+ @@consequents = {} # @private
157
+
158
+ ##
159
+ # @private
160
+ def self.inherited(subclass)
161
+ @@antecedents[subclass] = []
162
+ @@constraints[subclass] = {}
163
+ @@consequents[subclass] = []
164
+ end
165
+
166
+ ##
167
+ # Defines an antecedent for this rule class.
168
+ #
169
+ # @param [Symbol, URI] s
170
+ # @param [Symbol, URI] p
171
+ # @param [Symbol, URI] o
172
+ # @return [void]
173
+ def self.antecedent(s, p, o)
174
+ @@antecedents[self] << RDF::Statement.new(s, p, o)
175
+ end
176
+
177
+ ##
178
+ # Defines a type constraint for this rule class.
179
+ #
180
+ # @param [Hash{Symbol => Class}] types
181
+ # @return [void]
182
+ def self.constraint(types = {})
183
+ @@constraints[self].merge!(types)
184
+ end
185
+
186
+ ##
187
+ # Defines the consequent of this rule class.
188
+ #
189
+ # @param [Symbol, URI] s
190
+ # @param [Symbol, URI] p
191
+ # @param [Symbol, URI] o
192
+ # @return [void]
193
+ def self.consequent(s, p, o)
194
+ @@consequents[self] << RDF::Statement.new(s, p, o)
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,140 @@
1
+ module RDFS
2
+ ##
3
+ # The RDFS entailment rules.
4
+ #
5
+ # @see http://www.w3.org/TR/rdf-mt/
6
+ module Semantics
7
+ ##
8
+ # RDF entailment rule `rdf1`.
9
+ #
10
+ # @see http://www.w3.org/TR/rdf-mt/#RDFRules
11
+ class RDF1 < Rule
12
+ antecedent :uuu, :aaa, :yyy
13
+ consequent :aaa, RDF.type, RDF.Property
14
+ end
15
+
16
+ ##
17
+ # RDFS entailment rule `rdfs2` for `rdfs:domain`.
18
+ #
19
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
20
+ class RDFS2 < Rule
21
+ antecedent :aaa, RDFS.domain, :xxx
22
+ antecedent :uuu, :aaa, :yyy
23
+ consequent :uuu, RDF.type, :xxx
24
+ end
25
+
26
+ ##
27
+ # RDFS entailment rule `rdfs3` for `rdfs:range`.
28
+ #
29
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
30
+ class RDFS3 < Rule
31
+ antecedent :aaa, RDFS.range, :xxx
32
+ antecedent :uuu, :aaa, :vvv
33
+ consequent :vvv, RDF.type, :xxx
34
+ end
35
+
36
+ ##
37
+ # RDFS entailment rule `rdfs4a`.
38
+ #
39
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
40
+ class RDFS4a < Rule
41
+ antecedent :uuu, :aaa, :xxx
42
+ consequent :uuu, RDF.type, RDFS.Resource
43
+ end
44
+
45
+ ##
46
+ # RDFS entailment rule `rdfs4b`.
47
+ #
48
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
49
+ class RDFS4b < Rule
50
+ antecedent :uuu, :aaa, :vvv
51
+ constraint :vvv => RDF::Node
52
+ consequent :vvv, RDF.type, RDFS.Resource
53
+ end
54
+
55
+ ##
56
+ # RDFS entailment rule `rdfs5` for `rdfs:subPropertyOf`.
57
+ #
58
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
59
+ class RDFS5 < Rule
60
+ antecedent :uuu, RDFS.subPropertyOf, :vvv
61
+ antecedent :vvv, RDFS.subPropertyOf, :xxx
62
+ consequent :uuu, RDFS.subPropertyOf, :xxx
63
+ end
64
+
65
+ ##
66
+ # RDFS entailment rule `rdfs6` for `rdfs:subPropertyOf`.
67
+ #
68
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
69
+ class RDFS6 < Rule
70
+ antecedent :uuu, RDF.type, RDF.Property
71
+ consequent :uuu, RDFS.subPropertyOf, :uuu
72
+ end
73
+
74
+ ##
75
+ # RDFS entailment rule `rdfs7` for `rdfs:subPropertyOf`.
76
+ #
77
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
78
+ class RDFS7 < Rule
79
+ antecedent :aaa, RDFS.subPropertyOf, :bbb
80
+ antecedent :uuu, :aaa, :yyy
81
+ consequent :uuu, :bbb, :yyy
82
+ end
83
+
84
+ ##
85
+ # RDFS entailment rule `rdfs8` for `rdfs:subClassOf`.
86
+ #
87
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
88
+ class RDFS8 < Rule
89
+ antecedent :uuu, RDF.type, RDFS.Class
90
+ consequent :uuu, RDFS.subClassOf, RDFS.Resource
91
+ end
92
+
93
+ ##
94
+ # RDFS entailment rule `rdfs9` for `rdfs:subClassOf`.
95
+ #
96
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
97
+ class RDFS9 < Rule
98
+ antecedent :uuu, RDFS.subClassOf, :xxx
99
+ antecedent :vvv, RDF.type, :uuu
100
+ consequent :vvv, RDF.type, :xxx
101
+ end
102
+
103
+ ##
104
+ # RDFS entailment rule `rdfs10` for `rdfs:subClassOf`.
105
+ #
106
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
107
+ class RDFS10 < Rule
108
+ antecedent :uuu, RDF.type, RDFS.Class
109
+ consequent :uuu, RDFS.subClassOf, :uuu
110
+ end
111
+
112
+ ##
113
+ # RDFS entailment rule `rdfs11` for `rdfs:subClassOf`.
114
+ #
115
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
116
+ class RDFS11 < Rule
117
+ antecedent :uuu, RDFS.subClassOf, :vvv
118
+ antecedent :vvv, RDFS.subClassOf, :xxx
119
+ consequent :uuu, RDFS.subClassOf, :xxx
120
+ end
121
+
122
+ ##
123
+ # RDFS entailment rule `rdfs12`.
124
+ #
125
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
126
+ class RDFS12 < Rule
127
+ antecedent :uuu, RDF.type, RDFS.ContainerMembershipProperty
128
+ consequent :uuu, RDFS.subPropertyOf, RDFS.member
129
+ end
130
+
131
+ ##
132
+ # RDFS entailment rule `rdfs13`.
133
+ #
134
+ # @see http://www.w3.org/TR/rdf-mt/#RDFSRules
135
+ class RDFS13 < Rule
136
+ antecedent :uuu, RDF.type, RDFS.Datatype
137
+ consequent :uuu, RDFS.subClassOf, RDFS.Literal
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,19 @@
1
+ module RDFS
2
+ module VERSION
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ TINY = 0
6
+ EXTRA = nil
7
+
8
+ STRING = [MAJOR, MINOR, TINY].join('.')
9
+ STRING << "-#{EXTRA}" if EXTRA
10
+
11
+ ##
12
+ # @return [String]
13
+ def self.to_s() STRING end
14
+
15
+ ##
16
+ # @return [String]
17
+ def self.to_str() STRING end
18
+ end
19
+ end
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+ require 'pathname'
3
+ require 'rdf'
4
+ require 'rdfs'
5
+ require 'rdfs/rule'
6
+
7
+ class Pathname
8
+ def /(path)
9
+ (self + path).expand_path
10
+ end
11
+ end # class Pathname
12
+
13
+ spec_dir_path = Pathname(__FILE__).dirname.expand_path
14
+ require spec_dir_path.parent + 'lib/rdfs'
15
+
16
+ # # require fixture resources
17
+ Dir[spec_dir_path + "lib/rdfs/*.rb"].each do |fixture_file|
18
+ require fixture_file
19
+ end
20
+
21
+ # # require fixture resources
22
+ # Dir[spec_dir_path + "fixtures/*.rb"].each do |fixture_file|
23
+ # require fixture_file
24
+ # end
25
+
26
+
27
+ require 'rspec'
28
+ # optionally add autorun support
29
+ #require 'rspec/autorun'
30
+
31
+ Rspec.configure do |c|
32
+ c.mock_with :rspec
33
+ end
@@ -0,0 +1,104 @@
1
+ #require 'spec_helper'
2
+ require 'rdf'
3
+
4
+ require 'rdfs'
5
+ require 'rdfs/rule'
6
+ include RDF
7
+ include ::RDFS::Semantics
8
+
9
+ describe ::RDF::Statement do
10
+ it "should be able to substitute a mapping into itself" do
11
+ statement = Statement.new(:aaa, :xxx, FOAF.person)
12
+ mapping = {RDF::Node.new(:aaa) => 'rdf:friend', RDF::Node.new(:xxx) => 'rdf:knows'}
13
+ a = statement.with_substitutions(mapping)
14
+ a.should eql Statement.new('rdf:friend', 'rdf:knows', FOAF.person)
15
+ end
16
+
17
+ it "should know its specificity" do
18
+ a1 = Statement.new(:aaa, RDFS.domain, :xxx)
19
+ a2 = Statement.new(:uuu, :aaa, :yyy)
20
+
21
+ [a1, a2].collect(&:specificity).should == [1,0]
22
+ [a1, a2].sort_by(&:specificity).should == [a2,a1]
23
+ end
24
+
25
+ end
26
+
27
+
28
+ describe ::RDFS::Rule do
29
+
30
+ before(:each) do
31
+ @rule1 = RDF1.new
32
+ @statement1 = Statement.new('joe:shmoe', 'rdf:jerk', 'schmuck')
33
+ @matching_statements_1 = [Statement.new('rdf:jerk', RDF.type, RDF.Property)]
34
+
35
+ @rule2 = RDFS2.new
36
+ @statement2 = Statement.new('rdf:annoys', RDFS.domain, FOAF.person)
37
+ @statement3 = Statement.new('tom', 'rdf:annoys', 'jerry')
38
+ @statement4 = Statement.new('tom', RDF.type, FOAF.person)
39
+ end
40
+
41
+ it "should know its antecedents" do
42
+ @rule1.antecedents.should eql([Statement.new(:uuu, :aaa, :yyy)])
43
+ end
44
+
45
+ it "should know its consequents" do
46
+ @rule1.consequents.should eql([Statement.new(:aaa, RDF.type, RDF.Property)])
47
+ end
48
+
49
+ it "should be able to substitute a mapping into consequents" do
50
+ consequents = [Statement.new(:aaa, :xxx, FOAF.person)]
51
+ mapping = {RDF::Node.new(:aaa) => 'rdf:friend', RDF::Node.new(:xxx) => 'rdf:knows'}
52
+ a = ::RDFS::Rule.substitute(consequents, mapping)
53
+ a.should eql [Statement.new('rdf:friend', 'rdf:knows', FOAF.person)]
54
+ end
55
+
56
+ it "should be able to do unitary matches" do
57
+ antecedent = Statement.new :uuu, :aaa, :yyy
58
+ @statement1 = Statement.new('joe:shmoe', 'rdf:jerk', 'schmuck')
59
+ ::RDFS::Rule.unitary_match(antecedent, @statement1).should be_true
60
+ end
61
+
62
+ it "should not unitary match if non-placeholders are different" do
63
+ a1 = Statement.new(:aaa, RDFS.domain, :xxx)
64
+ s1 = Statement.new('rdf:annoys', RDFS.subPropertyOf, FOAF.person)
65
+ ::RDFS::Rule.unitary_match(a1, s1).should be_false
66
+ end
67
+
68
+
69
+ context "should generate consequents from pairs of statements that match the antecedents" do
70
+
71
+ it "with just one antecedent and one consequent" do
72
+ @rule1[@statement1].should eql(@matching_statements_1)
73
+
74
+ @rule_rdfs4a = RDFS4a.new
75
+ @statements_matching_rule_rdfs4a = [Statement.new('rdf:annoys', RDF.type, RDFS.Resource)]
76
+ @rule_rdfs4a[@statement2].should eql @statements_matching_rule_rdfs4a
77
+ end
78
+
79
+ it "matching should be commutative" do
80
+ @rule2[@statement2,@statement3].should eql @rule2[@statement3,@statement2]
81
+ end
82
+
83
+ it "with multiple antecedents and one consequent" do
84
+ @rule2 = RDFS2.new
85
+ @rule2[@statement2,@statement3].should eql([@statement4])
86
+ end
87
+
88
+ it "with multiple antecedents" do
89
+ @rule2[@statement2,@statement3].should eql [Statement.new('tom', RDF.type, FOAF.person)]
90
+ @rule2[@statement3,@statement2].should eql [Statement.new('tom', RDF.type, FOAF.person)]
91
+ end
92
+
93
+ end
94
+
95
+ context "should not generate consequents from pairs of statements that don't match the antecedents" do
96
+ it "with multiple antecedents" do
97
+ @rule2 = RDFS2.new
98
+
99
+ @statement2 = Statement.new('rdf:annoys', RDFS.domain, FOAF.person)
100
+ d = Statement.new('foo', 'bar', 'baz')
101
+ @rule2[@statement2,d].should be_false
102
+ end
103
+ end
104
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pius-rdfs
3
+ version: !ruby/object:Gem::Version
4
+ hash: -1713379756426313520
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
+ platform: ruby
12
+ authors:
13
+ - Arto Bendiken
14
+ - Pius Uzamere
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-10-09 00:00:00 -04:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rdf-spec
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ hash: 363868379743904425
31
+ segments:
32
+ - 0
33
+ - 2
34
+ - 0
35
+ version: 0.2.0
36
+ type: :development
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ name: rspec
40
+ prerelease: false
41
+ requirement: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: -2689461885439978514
47
+ segments:
48
+ - 1
49
+ - 3
50
+ - 0
51
+ version: 1.3.0
52
+ type: :development
53
+ version_requirements: *id002
54
+ - !ruby/object:Gem::Dependency
55
+ name: yard
56
+ prerelease: false
57
+ requirement: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: -1257173255691836839
63
+ segments:
64
+ - 0
65
+ - 5
66
+ - 6
67
+ version: 0.5.6
68
+ type: :development
69
+ version_requirements: *id003
70
+ - !ruby/object:Gem::Dependency
71
+ name: rdf
72
+ prerelease: false
73
+ requirement: &id004 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ hash: 363868379743904425
79
+ segments:
80
+ - 0
81
+ - 2
82
+ - 0
83
+ version: 0.2.0
84
+ type: :runtime
85
+ version_requirements: *id004
86
+ description: RDFS.rb is a forward-chaining inference engine that implements the RDF Schema (RDFS) entailment rules.
87
+ email: pius@alum.mit.edu
88
+ executables: []
89
+
90
+ extensions: []
91
+
92
+ extra_rdoc_files: []
93
+
94
+ files:
95
+ - AUTHORS
96
+ - README
97
+ - UNLICENSE
98
+ - VERSION
99
+ - lib/rdfs/reasoner.rb
100
+ - lib/rdfs/repository.rb
101
+ - lib/rdfs/rule.rb
102
+ - lib/rdfs/semantics.rb
103
+ - lib/rdfs/version.rb
104
+ - lib/rdfs.rb
105
+ - spec/spec_helper.rb
106
+ - spec/unit/rule_spec.rb
107
+ has_rdoc: true
108
+ homepage: http://rdfs.rubyforge.org/
109
+ licenses:
110
+ - Public Domain
111
+ post_install_message:
112
+ rdoc_options: []
113
+
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: -2660243542901265017
122
+ segments:
123
+ - 1
124
+ - 8
125
+ - 2
126
+ version: 1.8.2
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ hash: -2953524206653324603
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ requirements: []
137
+
138
+ rubyforge_project: rdfs
139
+ rubygems_version: 1.3.7
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: A forward-chaining inference engine that implements the RDFS entailment rules.
143
+ test_files:
144
+ - spec/spec_helper.rb
145
+ - spec/unit/rule_spec.rb