Class: Theory

Inherits:
Object show all
Defined in:
lib/Theory.rb

Direct Known Subclasses

TheoryImplementation

Constant Summary collapse

@@theory_id =
0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dependents, action, results, example_runtime_method = nil) ⇒ Theory

Returns a new instance of Theory.

Parameters:

  • example_runtime_method (defaults to: nil)

    A runtime method instance with this theories action applied to it and which meets the theories dependents with a certain set of test cases.



14
15
16
17
18
# File 'lib/Theory.rb', line 14

def initialize(dependents,action,results,example_runtime_method=nil)
  @dependents, @action, @results, @example_runtime_method = dependents, action, results, example_runtime_method
  @theory_id = @@theory_id
  @@theory_id += 1
end

Instance Attribute Details

#actionObject (readonly)

Returns the value of attribute action.



2
3
4
# File 'lib/Theory.rb', line 2

def action
  @action
end

#dependentsObject (readonly)

Returns the value of attribute dependents.



2
3
4
# File 'lib/Theory.rb', line 2

def dependents
  @dependents
end

#example_runtime_methodObject (readonly)

Returns the value of attribute example_runtime_method.



2
3
4
# File 'lib/Theory.rb', line 2

def example_runtime_method
  @example_runtime_method
end

#resultsObject

Returns the value of attribute results.



2
3
4
# File 'lib/Theory.rb', line 2

def results
  @results
end

#theory_idObject (readonly)

Returns the value of attribute theory_id.



2
3
4
# File 'lib/Theory.rb', line 2

def theory_id
  @theory_id
end

#theory_instance_idObject

Returns the value of attribute theory_instance_id.



7
8
9
# File 'lib/Theory.rb', line 7

def theory_instance_id
  @theory_instance_id
end

Class Method Details

.load_theory(theory_id) ⇒ Object

Loads a particular theory that has been saved to a file

Raises:

  • (StandardError)


60
61
62
63
64
65
# File 'lib/Theory.rb', line 60

def self.load_theory(theory_id)
  directory_path = $LOC+File.join('test','fixtures','theories',theory_id.to_s)
  raise StandardError.new("Theory fixture #{theory_id} does not exist") unless(File.exists?(directory_path))
  dump_file = File.open(File.join(directory_path,'dump'),'r')
  return Marshal.load(dump_file)    
end

Instance Method Details

#all_theory_variablesObject

Returns an array of all the theory variables used within the theory.



187
188
189
190
191
192
193
194
195
196
# File 'lib/Theory.rb', line 187

def all_theory_variables
  
  # Get all the theory variables used in the @action, dependents and results 
  a = ([@action]+@dependents+@results).select{|x| x != nil}.inject([]) {|total,x| total += x.theory_variables }
  
  # Filter out only the uniq theory vairables
  # http://stackoverflow.com/questions/109781/uniq-by-object-attribute-in-ruby
  return a.inject({}) {|total,x| total[x.theory_variable_id]=x; total}.values
  
end

#componentsObject

Returns an array of all the theory components used in the theory.



267
268
269
# File 'lib/Theory.rb', line 267

def components
  return ([@action]+@dependents+@results).select{|x| x != nil}
end

#copyObject



20
21
22
23
# File 'lib/Theory.rb', line 20

def copy
  #return Theory.new(@dependents.copy,@action.copy,@results.copy)
  return Marshal.load(Marshal.dump(self))
end

#describeObject

Returns an abstract description of theory with colour matching for common variables.

TODO Include example here



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/Theory.rb', line 203

def describe
  
  # TODO include - theory_instance_id
  # Describe the despendencies
  description = 'if: '+"\n"
  @dependents.inject(description) {|description, x| description += x.describe(1) }
  
  # Describe the action
  unless @action.nil?
    description += "\n"+"action: \n"
    description += @action.describe(1)
  end
  
  # Describe the result
  description += "\n"+"result: \n"
  @results.inject(description) {|description, x| description += x.describe(1) }
  return description
    
end

#find_component(component_id) ⇒ Object

Returns the component with the id supplied



85
86
87
# File 'lib/Theory.rb', line 85

def find_component(component_id)
  return (dependents+results).find {|x| x.theory_component_id == component_id}
end

#has_result_structure?(structure) ⇒ Boolean

Returns true if the theory contains a result that’s structure is similar to that of the supplied result implementation.

Parameters:

  • structure

    The theory result implementation that’s structure is compared with this theorie’s results.

Returns:



95
96
97
# File 'lib/Theory.rb', line 95

def has_result_structure?(structure)
  return @results.any? {|x| x.same_structure?(structure)}
end

#highest_theory_variable_idObject

Returns the highest theory variable id used by the theory



181
182
183
# File 'lib/Theory.rb', line 181

def highest_theory_variable_id
  return all_theory_variables.sort {|y,z| y.theory_variable_id <=> z.theory_variable_id }.reverse.first.theory_variable_id
end

#highlight(component_ids = []) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/Theory.rb', line 241

def highlight(component_ids=[])
  # @log.error("\033[0;31m\ "+msg+"\033[00m\ ")
  # Describe the despendencies
  description = 'if: '+"\n"
  @dependents.inject(description) do |description, x|
    if component_ids.include?(x.theory_component_id)
      description += "\033[0;31m\ "+x.write(1)+"\033[00m\ "+"\n"
    else
      description += x.write(1)+"\n"
    end
  end
  
  # Describe the action
  unless @action.nil?
    description += "\n"+"action: \n"
    description += @action.write(1)
  end
  
  # Describe the result
  description += "\n"+"result: \n"
  @results.inject(description) {|description, x| description += x.write(1)+"\n" }
  return description     
end

#identify_unchangedObject

Identify the dependents and actions that haven’t changed between adding the action.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/Theory.rb', line 31

def identify_unchanged

  # Identify the dependents that change after the action is added
  changing_dependents = []
  @dependents.each do |dependent|
    next if @results.any? {|x| x.write == dependent.write}
    changing_dependents << dependent 
  end        
  
  # Identify the results that don't occur in the dependents
  changing_results = []
  @results.each do |result|
    # TODO Should this use the changing_dependents
    next if @dependents.any? {|x| x.write == result.write}
    changing_results << result
  end
  
  # TODO  Stripping out the dependents will mean that they won't be 
  #       met and the theory might be dismissed unfairly.  e.g. it
  #       needs var1.kind_of?(RuntimeMethod).  It should probably start
  #       with the minimum and work backwards - e.g. adding the dependents
  #       until it doesn't fail.
  
  # Create a new runtime method with the irrelevant changes removed    
  return Theory.new(changing_dependents,action.copy,changing_results,example_runtime_method.copy)
end

#irrelevant?Boolean

Returns:



25
26
27
# File 'lib/Theory.rb', line 25

def irrelevant?
  dependents.empty? and results.empty? and action.nil?
end

#map_to(mapping, values = {}) ⇒ Object

}

}

Parameters:

  • mapping (1=>[], 2=>#<IntrinsicTestCases:0xb712d13c)

    , 3=>#<IntrinsicRuntimeMethod:0xb712c980>

  • values (1=>0, 2=><#TestCases> 3=><#Runtime Method>) (defaults to: {})

    alues { 1=>0, 2=><#TestCases> 3=><#Runtime Method>

Raises:

  • (StandardError)


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/Theory.rb', line 131

def map_to(mapping,values={})
  raise StandardError.new('Please use the maping datatype') unless mapping.kind_of?(Mapping)
  # return TheoryImplementation.new(
      # @dependents.collect {|y| y.map_to(mapping)},
      # @action ? @action.map_to(mapping) : nil,
      # @results.collect {|y| y.map_to(mapping)},
      # mapping,
      # values
    # )    
  return TheoryImplementation.new(
      @dependents.collect {|y| y.map_to(mapping)},
      @action ? @action.map_to(mapping) : nil,
      @results.collect {|y| y.map_to(mapping)},
      mapping,
      values
    )       
end

#orphan_action_variablesObject

Returns an array of any variables that only exist in the action. These are important for determining global ids, the results and dependents global id is determined my what they are connected to, these action variables aren’t connected to anything.



110
111
112
113
114
115
116
117
118
119
# File 'lib/Theory.rb', line 110

def orphan_action_variables
  return [] if @action.nil?
  excluded_variables = (@dependents+@results).inject([]) {|total,x| total += x.theory_variables }
  orphans = @action.theory_variables - excluded_variables
  # TODO  Should probably raise an error for this situation.
  # TODO  Actually as long as I include context when the value is added and the value it should
  #       be fine e.g. var2[:params][var3] for var3
  StandardLogger.instance.warning "You really should not have variables that are not in dependents - there is no context for the value"
  return orphans
end

#rewrite_permutations(realisable_variables, partial_mapping = Mapping.new()) ⇒ Object

TODO Need to write tests for this that use the mapping

Raises:

  • (StandardError)


150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/Theory.rb', line 150

def rewrite_permutations(realisable_variables,partial_mapping=Mapping.new())
  
  # Get an array of all the theory variables 
  a = all_theory_variables
  
  # Strip out the theory variables that have already been accounted for
  free_theory_variables = a.select {|x| !partial_mapping.has_key?(x.theory_variable_id) }
  
  # If all the mapping has been determines just return the single permutation
  return [self.map_to(partial_mapping)] if free_theory_variables.length == 0
  # TODO  This doesn't currentlt remove the initial finish values
  arrangements = (realisable_variables - partial_mapping.values).permutation(free_theory_variables.length).to_a   
  
  # Map the arrangements to specific theory variables ids.
  remaining_mapping = arrangements.inject([]) do |total,x|
    # TODO  I can probably get the 0 value to be the correct value
    hash_table = Mapping.new(Hash[*free_theory_variables.collect { |v| [v.theory_variable_id,0] }.flatten])
    free_theory_variables.zip(x) do |y,z|
      hash_table[y.theory_variable_id] = z
    end
    total << hash_table
  end    
  return remaining_mapping.inject([]) do |total,x|
    total << self.map_to(x.merge(partial_mapping))
  end
  
  raise StandardError.new('Need to complete the rest of the mapping with the available realisable variables')
  
end

#select_result_structure(structure) ⇒ Object

Returns the results thats structure matches that provided.



101
102
103
# File 'lib/Theory.rb', line 101

def select_result_structure(structure)
  return @results.select {|x| x.same_structure?(structure)}  
end

#uniq_theory_variables(min_id) ⇒ Object

Returns a new theory where all the theory variables ids start from the supplied value.



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/Theory.rb', line 70

def uniq_theory_variables(min_id)
    
  ids = all_theory_variables.inject([]) {|total,x| total << x.theory_variable_id}

  # Pair the olds with the new ones
  map = ids.inject(Mapping.new) {|total,x| total[x] = TheoryVariable.new(min_id); min_id += 1; total}
  
  # Duplicate the current theory and sustute the theory variables
  # TODO  Maybe shouldn't be a TheoryImplementation at this point
  return self.map_to(map)
  
end

#writeObject



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/Theory.rb', line 223

def write
  
  # Describe the despendencies
  description = 'if: '+"\n"
  @dependents.inject(description) {|description, x| description += x.write(1)+"\n" }
  
  # Describe the action
  unless @action.nil?
    description += "\n"+"action: \n"
    description += @action.write(1)
  end
  
  # Describe the result
  description += "\n"+"result: \n"
  @results.inject(description) {|description, x| description += x.write(1)+"\n" }
  return description    
end