rdf-isomorphic 0.2.0 → 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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
@@ -1,5 +1,6 @@
1
1
  require 'digest/sha1'
2
2
  require 'rdf'
3
+ require 'rdf/ntriples'
3
4
 
4
5
 
5
6
  module RDF
@@ -75,7 +76,6 @@ module RDF
75
76
  # @private
76
77
  def build_bijection_to(anon_stmts, nodes, other_anon_stmts, other_nodes, these_grounded_hashes = {}, other_grounded_hashes = {})
77
78
 
78
-
79
79
  # Create a hash signature of every node, based on the signature of
80
80
  # statements it exists in.
81
81
  # We also save hashes of nodes that cannot be reliably known; we will use
@@ -85,20 +85,31 @@ module RDF
85
85
  these_hashes, these_ungrounded_hashes = RDF::Isomorphic.hash_nodes(anon_stmts, nodes, these_grounded_hashes)
86
86
  other_hashes, other_ungrounded_hashes = RDF::Isomorphic.hash_nodes(other_anon_stmts, other_nodes, other_grounded_hashes)
87
87
 
88
+ # Grounded hashes are built at the same rate between the two graphs (if
89
+ # they are isomorphic). If there exists a grounded node in one that is
90
+ # not in the other, we can just return. Ungrounded nodes might still
91
+ # conflict, so we don't check them. This is a little bit messy in the
92
+ # middle of the method, and probably slows down isomorphic checks, but
93
+ # prevents almost-isomorphic cases from getting nutty.
94
+ return nil if these_hashes.values.any? { |hash|
95
+ !(other_hashes.values.member?(hash)) }
96
+ return nil if other_hashes.values.any? { |hash| !(these_hashes.values.member?(hash)) }
88
97
 
89
98
  # Using the created hashes, map nodes to other_nodes
99
+ # Ungrounded hashes will also be equal, but we keep the distinction
100
+ # around for when we recurse later (we only recurse on ungrounded nodes)
90
101
  bijection = {}
91
102
  nodes.each do | node |
92
- other_node, other_hash = other_hashes.find do | other_node, other_hash |
103
+ other_node, other_hash = other_ungrounded_hashes.find do | other_node, other_hash |
93
104
  # we need to use eql?, as coincedentally-named bnode identifiers are == in rdf.rb
94
- these_hashes[node].eql? other_hash
105
+ these_ungrounded_hashes[node].eql? other_hash
95
106
  end
96
107
  next unless other_node
97
108
  bijection[node] = other_node
98
-
99
- # we need to delete , as we don't want two nodes with the same hash
100
- # to be mapped to the same other_node.
101
- other_hashes.delete other_node
109
+
110
+ # Deletion is required to keep counts even; two nodes with identical
111
+ # signatures can biject to each other at random.
112
+ other_ungrounded_hashes.delete other_node
102
113
  end
103
114
 
104
115
  # bijection is now a mapping of nodes to other_nodes. If all are
@@ -166,17 +177,26 @@ module RDF
166
177
  # grounded, other nodes can then use it to decide their own state of
167
178
  # grounded.
168
179
  while hash_needed
169
- hash_needed = false
180
+ starting_grounded_nodes = hashes.size
170
181
  nodes.each do | node |
171
182
  unless hashes.member? node
172
183
  grounded, hash = node_hash_for(node, statements, hashes)
173
184
  if grounded
174
- hash_needed = true
175
185
  hashes[node] = hash
176
186
  end
177
187
  ungrounded_hashes[node] = hash
178
188
  end
179
189
  end
190
+ # after going over the list, any nodes with a unique hash can be marked
191
+ # as grounded, even if we have not tied them back to a root yet.
192
+ uniques = {}
193
+ ungrounded_hashes.each do |node, hash|
194
+ uniques[hash] = uniques[hash].is_a?(RDF::Node) ? false : node
195
+ end
196
+ uniques.each do |hash, node|
197
+ hashes[node] = hash unless node == false
198
+ end
199
+ hash_needed = starting_grounded_nodes != hashes.size
180
200
  end
181
201
  [hashes,ungrounded_hashes]
182
202
  end
@@ -245,6 +265,10 @@ module RDF
245
265
  hashes[node]
246
266
  when node.node?
247
267
  "a blank node"
268
+ # RDF.rb auto-boxing magic makes some literals the same when they
269
+ # should not be; the ntriples serializer will take care of us
270
+ when node.literal?
271
+ node.class.name + RDF::NTriples.serialize(node)
248
272
  else
249
273
  node.to_s
250
274
  end
@@ -1,7 +1,7 @@
1
1
  module RDF::Isomorphic
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 2
4
+ MINOR = 3
5
5
  TINY = 0
6
6
  EXTRA = nil
7
7
 
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
7
+ - 3
8
8
  - 0
9
- version: 0.2.0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Ben Lavender
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-18 00:00:00 -05:00
18
+ date: 2010-10-26 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency