Class: KVDAG::Vertex

Inherits:
Object
  • Object
show all
Includes:
Comparable, AttributeNode
Defined in:
lib/kvdag/vertex.rb

Overview

A vertex in a KVDAG

Instance Attribute Summary collapse

Attributes included from AttributeNode

#attrs

Instance Method Summary collapse

Methods included from AttributeNode

#[], #[]=, #fetch, #filter, #match?, #merge!, #to_hash

Constructor Details

#initialize(dag, attrs = {}) ⇒ Vertex

Returns a new instance of Vertex.



18
19
20
21
22
23
24
25
# File 'lib/kvdag/vertex.rb', line 18

def initialize(dag, attrs = {})
  @edges = Set.new
  @dag = dag
  @attrs = dag.hash_proxy_class.new(attrs)
  @child_cache = Set.new

  @dag.vertices << self
end

Instance Attribute Details

#dagObject (readonly)

Returns the value of attribute dag.



8
9
10
# File 'lib/kvdag/vertex.rb', line 8

def dag
  @dag
end

#edgesObject (readonly)

Returns the value of attribute edges.



9
10
11
# File 'lib/kvdag/vertex.rb', line 9

def edges
  @edges
end

Instance Method Details

#<=>(other) ⇒ Object

Comparable ordering for a DAG:

Reachable vertices are lesser. Unreachable vertices are equal.



123
124
125
126
127
# File 'lib/kvdag/vertex.rb', line 123

def <=>(other)
  return -1 if reachable?(other)
  return 1 if reachable_from?(other)
  return 0
end

#ancestorsObject



101
102
103
104
105
# File 'lib/kvdag/vertex.rb', line 101

def ancestors
  result = Set.new([self])
  parents.each {|p| result += p.ancestors }
  result
end

#children(filter = {}, &block) ⇒ Object

:call-seq:

vtx.children                 -> all children
vtx.children(filter)         -> children matching +filter+
vtx.children {|cld| ... }    -> call block with each child

Returns the set of all direct children, possibly filtered by #match? expressions. If a block is given, call it with each child.



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/kvdag/vertex.rb', line 63

def children(filter={}, &block)
  result = @child_cache.select {|child|
             child.match?(filter)
           }

  if block_given?
    result.each(&block)
  else
    result
  end
end

#descendantsObject

Return the set of this object and all its children, and their children, recursively

This is the same as all #reachable_from? vertices.



112
113
114
115
116
# File 'lib/kvdag/vertex.rb', line 112

def descendants
  result = Set.new([self])
  children.each {|c| result += c.descendants }
  result
end

#edge(other, attrs = {}) ⇒ Object

Create an edge towards an other vertex, optionally loaded with key-values.

A KVDAG::VertexError is raised if vertices belong to different KVDAG.

A KVDAG::CyclicError is raised if the edge would cause a cycle in the KVDAG.

Raises:



138
139
140
141
142
143
144
145
146
147
# File 'lib/kvdag/vertex.rb', line 138

def edge(other, attrs = {})
  other = other.to_vertex unless other.is_a?(Vertex)
  raise VertexError.new("Not in the same DAG") if @dag != other.dag
  raise CyclicError.new("Would become cyclic") if other.reachable?(self)

  edge = Edge.new(@dag, other, attrs)
  @edges << edge
  other.add_child(self)
  edge
end

#inspectObject Also known as: to_s



27
28
29
# File 'lib/kvdag/vertex.rb', line 27

def inspect
  "#<%s @attr=%s @edges=%s>" % [self.class, @attrs.to_hash, @edges.to_a]
end

#parents(filter = {}, &block) ⇒ Object

:call-seq:

vtx.parents                 -> all parents
vtx.parents(filter)         -> parents matching +filter+
vtx.parents {|cld| ... }    -> call block with each parent

Returns the set of all direct parents, possibly filtered by #match? expressions. If a block is given, call it with each parent.



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/kvdag/vertex.rb', line 41

def parents(filter={}, &block)
  result = Set.new(edges.map {|edge|
                     edge.to_vertex
                   }.select {|parent|
                     parent.match?(filter)
                   })

  if block_given?
    result.each(&block)
  else
    result
  end
end

#reachable?(other) ⇒ Boolean

Is other vertex reachable via any of my #edges?

A KVDAG::VertexError is raised if vertices belong to different KVDAG.

Returns:

  • (Boolean)

Raises:



80
81
82
83
84
# File 'lib/kvdag/vertex.rb', line 80

def reachable?(other)
  raise VertexError.new("Not in the same DAG") unless @dag.equal?(other.dag)

  equal?(other) || parents.any? {|parent| parent.reachable?(other)}
end

#reachable_from?(other) ⇒ Boolean

Am I reachable from other via any of its #edges?

A KVDAG::VertexError is raised if vertices belong to different KVDAG.

Returns:

  • (Boolean)


91
92
93
# File 'lib/kvdag/vertex.rb', line 91

def reachable_from?(other)
  other.reachable?(self)
end

#to_hash_proxyObject

Return the proxied key-value hash tree visible from this vertex via its edges and all its ancestors.

Calling #to_hash instead will return a regular hash tree, without any special properties, e.g. for serializing as YAML or JSON.



155
156
157
158
159
160
161
# File 'lib/kvdag/vertex.rb', line 155

def to_hash_proxy
  result = @dag.hash_proxy_class.new
  edges.each do |edge|
    result.merge!(edge.to_hash_proxy)
  end
  result.merge!(@attrs)
end