lib/rbbt/association/item.rb in rbbt-util-5.14.26 vs lib/rbbt/association/item.rb in rbbt-util-5.14.28
- old
+ new
@@ -5,10 +5,25 @@
annotation :knowledge_base
annotation :database
annotation :reverse
+ property :name => :single do
+ [source_entity, target_entity].collect{|e| e.respond_to?(:name)? e.name || e : e } * "~"
+ end
+
+ property :full_name => :single do
+ database ? [database, name] * ":" : name
+ end
+
+ property :invert => :single do
+ s,_sep,t= self.partition "~"
+ inverted = self.annotate([t,s] * _sep)
+ inverted.reverse = ! reverse
+ inverted
+ end
+
property :namespace => :both do
knowledge_base.namespace
end
property :part => :array2single do
@@ -42,10 +57,14 @@
property :target_entity => :array2single do
type = reverse ? knowledge_base.source(database) : knowledge_base.target(database)
knowledge_base.annotate self.target, type, database #if self.target.any?
end
+ property :undirected => :both do
+ knowledge_base.undirected(database)
+ end
+
property :source_entity => :array2single do
type = reverse ? knowledge_base.target(database) : knowledge_base.source(database)
knowledge_base.annotate self.source, type #if self.source.any?
end
@@ -82,31 +101,50 @@
tsv.entity_options.merge! options
end
tsv
end
- def self.incidence(pairs, key_field = nil)
+ def self.incidence(pairs, key_field = nil, &block)
matrix = {}
targets = []
sources = []
matches = {}
- pairs.each do |p|
+ pairs.inject([]){|acc,m| acc << m; acc << m.invert if m.respond_to?(:undirected) and m.undirected; acc }.each do |p|
s, sep, t = p.partition "~"
+
sources << s
targets << t
- matches[s] ||= Hash.new{false}
- matches[s][t] = true
+ if block_given?
+ matches[s] ||= Hash.new{nil}
+ value = block.call p
+ matches[s][t] = value unless value.nil? or (mv = matches[s][t] and value > mv)
+ else
+ matches[s] ||= Hash.new{true}
+ matches[s][t] ||= true
+ end
end
sources.uniq!
targets = targets.uniq.sort
matches.each do |s,hash|
matrix[s] = hash.values_at(*targets)
end
defined?(TSV)? TSV.setup(matrix, :key_field => (key_field || "Source") , :fields => targets, :type => :list) : matrix
+ end
+
+ def self.adjacency(pairs, key_field = nil, &block)
+ incidence = incidence(pairs, key_field, &block)
+
+ targets = incidence.fields
+ adjacency = TSV.setup({}, :key_field => incidence.key_field, :fields => ["Target"], :type => :double)
+ TSV.traverse incidence, :into => adjacency, :unnamed => true do |k,values|
+ target_values = targets.zip(values).reject{|t,v| v.nil? }.collect{|t,v| [t,v]}
+ next if target_values.empty?
+ [k, Misc.zip_fields(target_values)]
+ end
end
def self._select_match(orig, elem)
if Array === orig and Array === elem
(orig & elem).any?