Class: RDF::N3::Reasoner

Inherits:
Object show all
Includes:
Enumerable, Mutable, Util::Logger
Defined in:
vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb

Overview

A Notation-3/Turtle reasoner in Ruby

Takes either a parsed formula or an RDF::Queryable and updates it by reasoning over formula defined within the queryable.

Author:

Constant Summary

Constants included from Util::Logger

Util::Logger::IOWrapper

Instance Attribute Summary collapse

Attributes included from Enumerable

#existentials, #universals

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util::Logger

#log_debug, #log_depth, #log_error, #log_fatal, #log_info, #log_recover, #log_recovering?, #log_statistics, #log_warn, #logger

Methods included from Mutable

#<<, add_entailment, #apply_changeset, #clear, #delete, #delete_insert, #delete_statement, #delete_statements, #entail, #entail!, #immutable?, #insert, #load, #method_missing, #mutable?, #respond_to_missing?, #snapshot, #update

Methods included from Util::Aliasing::LateBound

#alias_method

Methods included from Writable

#<<, #insert, #insert_graph, #insert_reader, #insert_statements, #writable?

Methods included from Readable

#readable?

Methods included from Enumerable

add_entailment, #contain?, #dump, #each_graph, #each_object, #each_predicate, #each_quad, #each_statement, #each_subject, #each_term, #each_triple, #entail, #enum_graph, #enum_object, #enum_predicate, #enum_quad, #enum_statement, #enum_subject, #enum_term, #enum_triple, #graph_names, #has_graph?, #has_object?, #has_predicate?, #has_quad?, #has_statement?, #has_subject?, #has_term?, #has_triple?, #invalid?, #method_missing, #objects, #predicates, #project_graph, #quads, #respond_to_missing?, #statements, #subjects, #supports?, #terms, #to_a, #to_h, #to_set, #triples, #valid?, #validate!

Methods included from Countable

#count, #empty?

Methods included from Isomorphic

#bijection_to, #isomorphic_with?

Constructor Details

#initialize(input, **options) {|reasoner| ... } ⇒ RDF::N3::Reasoner

Initializes a new reasoner. If input is an IO or string, it is taken as n3 source and parsed first. Otherwise, it is a parsed formula.

It returns the evaluated formula, or yields triples.

Examples:

Initializing from a reader

reader = RDF::N3::Reader.new(":a :b :c .")
reasoner = RDF::N3::Reasoner.new(reader)
reasoner.each_triple {}

Initializing as a mutable

reasoner = RDF::N3::Reasoner.new do |r|
  r << RDF::N3::Reader.new(":a :b :c .")
end
reasoner.each_triple {}

Initializing with multiple inputs

reasoner = RDF::N3::Reasoner.new
RDF::NTriples::Reader.open("example.nt") {|r| reasoner << r}
RDF::N3::Reader.open("rules.n3") {|r| reasoner << r}
reasoner.each_triple {}

Parameters:

Options Hash (**options):

  • :base_uri (#to_s) — default: nil

    the base URI to use when resolving relative URIs (for acessing intermediate parser productions)

Yields:

  • (reasoner)

    self

Yield Parameters:

Yield Returns:

  • (void)

    ignored



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 61

def initialize(input, **options, &block)
  @options = options
  @mutable = case input
  when RDF::Mutable then input
  when RDF::Enumerable then RDF::Repository.new {|r| r << input}
  else RDF::Repository.new
  end

  log_debug("reasoner: expression", options) {SXP::Generator.string(formula.to_sxp_bin)}

  if block_given?
    case block.arity
      when 0 then instance_eval(&block)
      else block.call(self)
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class RDF::Mutable

Instance Attribute Details

#formulaRDF::N3::Algebra::Formula (readonly)

Returns the top-level formula for this file



16
17
18
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 16

def formula
  @formula
end

Class Method Details

.open(file) {|reasoner| ... } ⇒ RDF::N3::Reasoner

Opens a Notation-3 file, and parses it to initialize the reasoner

Parameters:

Yields:

  • (reasoner)

    self

Yield Parameters:

Yield Returns:

  • (void)

    ignored

Returns:



25
26
27
28
29
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 25

def self.open(file)
  RDF::N3::Reader.open(file, **options) do |reader|
    RDF::N3::Reasoner.new(reader, **options, &block)
  end
end

Instance Method Details

#conclusions {|statement| ... } #conclusionsEnumerator<RDF::Statement> Also known as: each_conclusion

Yields conclusions, excluding formulae and those statements in the original dataset, or returns an enumerator over the conclusions

Overloads:

Yields:

  • (statement)

Yield Parameters:

Returns:

  • (RDF::Enumerator)


212
213
214
215
216
217
218
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 212

def conclusions(&block)
  if block_given?
    # Invoke {#each} in the containing class:
    each_statement {|s| block.call(s) if s.inferred?}
  end
  enum_conclusions
end

#data {|statement| ... } #dataEnumerator<RDF::Statement> Also known as: each_datum

Yields data, excluding formulae or variables and statements referencing formulae or variables

Overloads:

Yields:

  • (statement)

Yield Parameters:

Returns:

  • (RDF::Enumerator)


170
171
172
173
174
175
176
177
178
179
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 170

def data(&block)
  if block_given?
    project_graph(nil) do |statement|
      block.call(statement) unless statement.variable? ||
                                  has_graph?(statement.subject) ||
                                  has_graph?(statement.object)
    end
  end
  enum_data
end

#dupObject

Returns a copy of this reasoner



81
82
83
84
85
86
87
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 81

def dup
  repo = RDF::Repository.new {|r| r << @mutable}
  self.class.new(repo) do |reasoner|
    reasoner.instance_variable_set(:@options, @options.dup)
    reasoner.instance_variable_set(:@formula, @formula.dup) if @formula
  end
end

#each(&block) ⇒ Object

Yields each statement in the datastore

@yieldparam [RDF::Statement] statement @yieldreturn [void] ignored @return [void]



151
152
153
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 151

def each(&block)
  @mutable.each(&block)
end

#enum_conclusionsEnumerator<RDF::Statement>

Returns an enumerator for #conclusions. FIXME: enum_for doesn't seem to be working properly in JRuby 1.7, so specs are marked pending



228
229
230
231
232
233
234
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 228

def enum_conclusions
  # Ensure that statements are queryable, countable and enumerable
  this = self
  RDF::Queryable::Enumerator.new do |yielder|
    this.send(:each_conclusion) {|y| yielder << y}
  end
end

#enum_dataEnumerator<RDF::Statement>

Returns an enumerator for #conclusions. FIXME: enum_for doesn't seem to be working properly in JRuby 1.7, so specs are marked pending



189
190
191
192
193
194
195
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 189

def enum_data
  # Ensure that statements are queryable, countable and enumerable
  this = self
  RDF::Queryable::Enumerator.new do |yielder|
    this.send(:each_datum) {|y| yielder << y}
  end
end

#execute(**options) {|statement| ... } ⇒ RDF::N3::Reasoner Also known as: reason!

Updates the datastore by reasoning over the formula, optionally yielding each conclusion; uses triples from the graph associated with this formula as the dataset over which to reason.

Parameters:

Options Hash (**options):

  • :apply (Boolean)
  • :think (Boolean)

Yields:

  • (statement)

Yield Parameters:

Returns:



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 107

def execute(**options, &block)
  @options[:logger] = options[:logger] if options.has_key?(:logger)

  # If thinking, continuously execute until results stop growing
  if options[:think]
    count = 0
    log_info("reasoner: think start") { "count: #{count}"}
    while @mutable.count > count
      count = @mutable.count
      dataset = RDF::Graph.new << @mutable.project_graph(nil)
      log_depth {formula.execute(dataset, **options)}
      @mutable << formula
    end
    log_info("reasoner: think end") { "count: #{count}"}
  else
    # Run one iteration
    log_info("reasoner: apply start") { "count: #{count}"}
    dataset = RDF::Graph.new << @mutable.project_graph(nil)
    log_depth {formula.execute(dataset, **options)}
    @mutable << formula
    log_info("reasoner: apply end") { "count: #{count}"}
  end

  log_debug("reasoner: datastore") {@mutable.to_sxp}

  conclusions(&block) if block_given?
  self
end

#insert_statement(statement)

This method returns an undefined value.

Inserts an RDF statement the datastore, resets formula.

Parameters:



94
95
96
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 94

def insert_statement(statement)
  @mutable.insert_statement(statement)
end

#reason(**options, &block) ⇒ Object

Reason with results in a duplicate datastore

See Also:

  • {execute}


141
142
143
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 141

def reason(**options, &block)
  self.dup.reason!(**options, &block)
end

#to_sxp_binArray

Returns the SPARQL S-Expression (SSE) representation of the parsed formula. Formulae are represented as subjects and objects in the containing graph, along with their universals and existentials

Returns:

See Also:



288
289
290
# File 'vendor/bundler/ruby/2.6.0/bundler/gems/rdf-n3-015ce184efe3/lib/rdf/n3/reasoner.rb', line 288

def to_sxp_bin
  formula.to_sxp_bin
end