Class: Wallace::Koza::KozaTree

Inherits:
Object
  • Object
show all
Defined in:
lib/modules/koza/koza_tree.rb

Overview

This class is used to represent Koza Trees, which in turn represent computer programs using Lisp-style S-expressions (program trees).

  • remove(n)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root) ⇒ KozaTree

Parameters:

  • root, the root node of this tree.



15
16
17
18
# File 'lib/modules/koza/koza_tree.rb', line 15

def initialize(root)
   @root = root
   calculate!
end

Instance Attribute Details

#depthObject (readonly)

Returns the value of attribute depth.



7
8
9
# File 'lib/modules/koza/koza_tree.rb', line 7

def depth
  @depth
end

#nodesObject (readonly)

Returns the value of attribute nodes.



7
8
9
# File 'lib/modules/koza/koza_tree.rb', line 7

def nodes
  @nodes
end

#rootObject

Returns the value of attribute root.



7
8
9
# File 'lib/modules/koza/koza_tree.rb', line 7

def root
  @root
end

Class Method Details

.to_lambda(args, tree) ⇒ Object

Compiles a given Koza Tree into a Ruby lambda function.

Parameters:

  • args, an array of the arguments to the function.

  • tree, the tree to compile to a lambda function.

Returns: the compiled lambda function.

NOTE: Trying to call ‘eval’ in an object method causes huge problems! Totally different semantics.



144
145
146
# File 'lib/modules/koza/koza_tree.rb', line 144

def self.to_lambda(args, tree)
  eval("lambda { |#{args.join(',')}| #{tree.to_ruby} }")
end

Instance Method Details

#[](index) ⇒ Object

Returns a node at a given index in the tree.



33
34
35
# File 'lib/modules/koza/koza_tree.rb', line 33

def [](index)
  @nodes[index]
end

#add(parent, child) ⇒ Object

Adds a node to the tree as the child of another node.

Parameters:

  • parent, The node to use as the parent of the new node.

  • child, The node to add to the tree.



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/modules/koza/koza_tree.rb', line 78

def add(parent, child)

  # Could throw an exception if there is no room for the child.
  parent.children << child
  child.parent = parent
  child.depth = parent.depth + 1

  @nodes << child
  @depth = child.depth if child.depth > @depth

end

#calculate!Object

(Re)calculates the list of nodes in the tree and their respective depths.



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/modules/koza/koza_tree.rb', line 54

def calculate!
  queue = [@root]
  @nodes = [@root]
  @root.depth = @depth = 0

  until queue.empty?
    n = queue.shift
    @depth = [@depth, n.depth].max
    n.children.each { |c| c.depth = n.depth + 1 }
    queue += n.children
    @nodes << n
  end
end

#cloneObject

Creates a clone of this tree (along with its nodes).



69
70
71
# File 'lib/modules/koza/koza_tree.rb', line 69

def clone
  Wallace::Koza::KozaTree.new(@root.clone)
end

#eval(args) ⇒ Object

Evaluates the S-expression given by this tree.

Parameters:

  • args, the arguments to the function / program (as a hash).



122
123
124
# File 'lib/modules/koza/koza_tree.rb', line 122

def eval(args)
  @root.eval(args)
end

#replace(n1, n2) ⇒ Object

Replaces a subtree in the tree with another subtree.

Parameters:

  • n1, the root node of the sub-tree being replaced.

  • n2, the root node of the replacement sub-tree.



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/modules/koza/koza_tree.rb', line 95

def replace(n1, n2)

  # Create a clone of n2 (to avoid affecting another tree).
  n2 = n2.clone
  
  # If n1 is the root of the tree then change the root to n2.
  if @root == n1
    @root = n2
    n2.parent = nil
    
  # Otherwise replace n1 with n2 in n1's parents list of children.
  else
    i = n1.parent.children.index(n1)
    n1.parent.children[i] = n2
    n2.parent = n1.parent
    n1.parent = nil
  end

  # Recalculate the node list and tree depth.
  calculate!

end

#sample(opts = {}) ⇒ Object

Samples a node (or number of nodes) from the tree at random.

Parameters:

  • n, the number of nodes to sample from the tree.

  • opts, a hash of keyword options for this method. -> size, the number of nodes to sample. -> random, the RNG to use for sampling.



27
28
29
30
# File 'lib/modules/koza/koza_tree.rb', line 27

def sample(opts = {})
  @nodes.sample(opts[:size], random: opts[:random] || Random.new) unless opts[:size].nil?
  @nodes.sample(random: opts[:random] || Random.new) 
end

#sizeObject Also known as: length

Returns the number of nodes in the tree.



38
39
40
# File 'lib/modules/koza/koza_tree.rb', line 38

def size
  @nodes.length
end

#to_lambda(args) ⇒ Object

Compiles this Koza Tree into a Ruby lambda function.

Parameters:

  • args, an array of the arguments to the function.

Returns: the compiled lambda function.



155
156
157
# File 'lib/modules/koza/koza_tree.rb', line 155

def to_lambda(args)
  self.class.to_lambda(args, self)
end

#to_rubyObject Also known as: to_s

Converts this tree into a Ruby program string.



127
128
129
# File 'lib/modules/koza/koza_tree.rb', line 127

def to_ruby
  @root.to_ruby
end