pius-rdfs 0.3.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.
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