Class: UnifiedChain
Overview
A unified chain is no longer editable - all the links have been added. Unlike a normal chain there is no mapping, all the theories should have the correct ids if they are linked. A unified chain is always complete.
Instance Attribute Summary
Attributes inherited from Chain
#chain_mapping
Instance Method Summary
collapse
-
#describe(tab = 0) ⇒ Object
-
#evaluate_statement(statement, runtime_method, test_cases) ⇒ Object
-
#extend_mapping(valid_mappings, component, runtime_method, test_cases, chain, available_values) ⇒ Object
-
#has_all_variables_been_found?(component, mappings) ⇒ Boolean
-
#identify_uniq_mappings(mappings) ⇒ Object
-
#implement(mapping) ⇒ Object
Return an implemented version of the chain where all the theory variables have been replaced with read values.
-
#implementation_permuatations(runtime_method, test_cases, mapping) ⇒ Object
Returns an array of implemented chains using the various value permutations.
-
#implementation_permuatations2(runtime_method, test_cases, mapping) ⇒ Object
-
#initialize(nodes) ⇒ UnifiedChain
constructor
TODO I don’t like that extending to Chain exposes the @nodes to public access.
-
#intrinsic_values_for_variable(id, component, mapping, runtime_method, test_cases, intrinsic_values) ⇒ Object
-
#mapping_permutations(keys, values) ⇒ Object
-
#missing_variables(component, mappings) ⇒ Object
-
#partial_chain(limit) ⇒ Object
-
#theory_variables ⇒ Object
Returns an array of all the theory variables in the chain.
-
#valid_mapping?(runtime_method, test_cases, statement, mapping) ⇒ Boolean
-
#valid_mapping_permutations(runtime_method, test_cases) ⇒ Object
-
#valid_statement?(statement, runtime_method, test_cases) ⇒ Boolean
-
#write(tab = 0) ⇒ Object
Methods inherited from Chain
#<<, #[], #add_link_to, #broken_link_count, #collect, #complete?, #copy, default_tail_theory, #duplicate_component_ids?, #each, #each_theory_progression, #empty?, #extension_permutaions, #first, #highlight_broken_links, #implementable?, #last, #length, #pop, #reverse, #shift, #solvable?, #theories_sequence, #unify_chain, #uniq_theory_variable_ids, #unmet_dependents, #unmet_dependents_and_link, #unmet_dependents_ids, #variables_creation
Constructor Details
TODO I don’t like that extending to Chain exposes the @nodes to public access
8
9
10
|
# File 'lib/UnifiedChain.rb', line 8
def initialize(nodes)
@nodes = nodes
end
|
Instance Method Details
#describe(tab = 0) ⇒ Object
16
17
18
|
# File 'lib/UnifiedChain.rb', line 16
def describe(tab=0)
return @nodes.inject('') {|total,x| total += x.describe}
end
|
#evaluate_statement(statement, runtime_method, test_cases) ⇒ Object
299
300
301
|
# File 'lib/UnifiedChain.rb', line 299
def evaluate_statement(statement,runtime_method,test_cases)
eval statement
end
|
#extend_mapping(valid_mappings, component, runtime_method, test_cases, chain, available_values) ⇒ Object
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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
179
180
181
182
183
184
185
186
|
# File 'lib/UnifiedChain.rb', line 131
def extend_mapping(valid_mappings,component,runtime_method,test_cases,chain,available_values)
new_mappings = []
component.theory_variables.each do |var|
next if valid_mappings.first.has_key?(var.theory_variable_id)
valid_mappings.each do |mapping|
implemented_chain = chain.implement(Mapping.new(mapping))
implemented_runtime_method = TheoryChainValidator.new.build_method_from_chain(
implemented_chain,runtime_method.copy,test_cases.copy
)
possible_values = available_values-mapping.values
begin
values = intrinsic_values_for_variable(
var.theory_variable_id,
component,
mapping,
implemented_runtime_method,
test_cases.copy,
possible_values
)
rescue NoMethodError => e
valid_mappings = valid_mappings-[mapping]
next
end
values = values.uniq
values.each do |value|
copied_mapping = mapping.copy
copied_mapping[var.theory_variable_id] = value
new_mappings << copied_mapping
end
end
end
new_mappings = identify_uniq_mappings(new_mappings)
longest_mapping = new_mappings.inject(0) do |highest,m|
if(m.length > highest)
highest = m.length
end
highest
end
res = new_mappings.select {|x| x.length == longest_mapping}
new_mappings = res
unless new_mappings.empty?
valid_mappings = new_mappings
end
return valid_mappings
end
|
#has_all_variables_been_found?(component, mappings) ⇒ Boolean
111
112
113
114
115
116
117
118
|
# File 'lib/UnifiedChain.rb', line 111
def has_all_variables_been_found?(component,mappings)
component.theory_variables.each do |var|
mappings.each do |mapping|
return false unless mapping.has_key? var.theory_variable_id
end
end
return true
end
|
#identify_uniq_mappings(mappings) ⇒ Object
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
# File 'lib/UnifiedChain.rb', line 188
def identify_uniq_mappings(mappings)
uniq_mappings = []
count = mappings.length
until mappings.empty?
mapping = mappings.shift
already_exists = mappings.any? do |x|
next false unless x.length == mapping.length
next false unless x.keys.sort == mapping.keys.sort
all_values_the_same = true
x.each do |key,value|
if mapping[key].class != value.class
all_values_the_same = false
end
if mapping[key].class == value.class
if mapping[key].kind_of?(IntrinsicLiteral)
if mapping[key].write != value.write
all_values_the_same = false
end
end
end
end
next false unless all_values_the_same
next true
end
unless already_exists
uniq_mappings << mapping
end
end
if uniq_mappings.length == 0 && count != 0
raise StandardError.new('uniq_mappings should not be 0')
end
return uniq_mappings
end
|
#implement(mapping) ⇒ Object
Return an implemented version of the chain where all the theory variables have been replaced with read values.
34
35
36
37
38
39
|
# File 'lib/UnifiedChain.rb', line 34
def implement(mapping)
implemented_nodes = @nodes.inject([]) do |total,theory|
total << theory.map_to(mapping)
end
return ImplementedChain.new(implemented_nodes,mapping)
end
|
#implementation_permuatations(runtime_method, test_cases, mapping) ⇒ Object
Returns an array of implemented chains using the various value permutations. Essential what it is looking for is mapping to convert all the theory variables to intrinsic variables.
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
|
# File 'lib/UnifiedChain.rb', line 318
def implementation_permuatations(runtime_method,test_cases,mapping)
return implementation_permuatations2(runtime_method,test_cases,mapping)
theory_variable_ids = theory_variables.collect {|x| x.theory_variable_id}
missing_intrinsic_values = theory_variable_ids-mapping.keys
generator = TheoryGenerator.new()
accessors, temp_mapping = generator.generate_accessors_and_mapping(test_cases,runtime_method,3)
if temp_mapping.length > missing_intrinsic_values.length
theory_variable_ids = self.theory_variables.collect {|x| x.theory_variable_id }
res = temp_mapping.values.collect {|x| x}
intrinsic_res = res.collect {|x| x.to_intrinsic}
value_permutaions = intrinsic_res.permutation(theory_variable_ids.length).to_a
uniq_value_permutations = value_permutaions.collect {|x| x.to_set}.uniq
possible_mappings = []
theory_variable_id_permutations = theory_variable_ids.permutation(theory_variable_ids.length).to_a
possible_mappings = []
theory_variable_id_permutations.each do |theory_variable_id_permutation|
uniq_value_permutations.each do |value_permutation|
m = Mapping.new
theory_variable_id_permutation.zip(value_permutation.to_a) do |key,value|
m[key] = value
end
possible_mappings << m
end
end
return possible_mappings.inject([]) { |total,mapping| total << self.copy.implement(mapping) }
else
raise StandardError.new('Could not generate enough real vlaues to test theory - try increasing the itterations')
end
end
|
#implementation_permuatations2(runtime_method, test_cases, mapping) ⇒ Object
41
42
43
44
45
46
47
|
# File 'lib/UnifiedChain.rb', line 41
def implementation_permuatations2(runtime_method,test_cases,mapping)
more_mapping = valid_mapping_permutations(runtime_method.copy,test_cases.copy)
return more_mapping.inject([]) { |total,mapping| total << self.copy.implement(mapping) }
end
|
#intrinsic_values_for_variable(id, component, mapping, runtime_method, test_cases, intrinsic_values) ⇒ Object
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
|
# File 'lib/UnifiedChain.rb', line 222
def intrinsic_values_for_variable(id,component,mapping,runtime_method,test_cases,intrinsic_values)
values = []
component.statements_with_variable(id).each do |statement|
reg = eval('/^var'+id.to_s+'\./')
if statement.write.match(reg)
intrinsic_values.each do |value|
temp_mapping = mapping.copy
temp_mapping[id] = value
if valid_mapping?(runtime_method.copy,test_cases.copy,statement,temp_mapping)
values << value
end
end
next
end
index_values = []
intrinsic_statement = statement.map_to(mapping)
if intrinsic_statement.select_all {|z| z.kind_of?(TheoryVariable)}.length > 0
if m = intrinsic_statement.write.match(/([\w\.]+)\[var(\d)+\]/)
method_call = $1
if m2 = method_call.match(/var(\d+)/)
next
end
literal = evaluate_statement(method_call,runtime_method.copy,test_cases.copy)
literal.length.times do |n|
index_values << IntrinsicLiteral.new(n)
end
end
end
values += index_values
variable_values = []
intrinsic_values.each do |value|
literal = intrinsic_statement.write.gsub(/var(\d)+/,value.write)
begin
eval literal
variable_values << value
rescue
next
end
end
values += variable_values
end
return values
end
|
#mapping_permutations(keys, values) ⇒ Object
287
288
289
290
291
|
# File 'lib/UnifiedChain.rb', line 287
def mapping_permutations(keys,values)
values.permutation(keys.length).to_a.inject([]) do |total,value_permutation|
total << Hash[*keys.zip(value_permutation).flatten]
end
end
|
#missing_variables(component, mappings) ⇒ Object
120
121
122
123
124
125
126
127
128
129
|
# File 'lib/UnifiedChain.rb', line 120
def missing_variables(component,mappings)
results = []
component.theory_variables.each do |var|
mappings.each do |mapping|
results << var unless mapping.has_key? var.theory_variable_id
end
end
return results
end
|
#partial_chain(limit) ⇒ Object
282
283
284
285
|
# File 'lib/UnifiedChain.rb', line 282
def partial_chain(limit)
links = @nodes[1..limit].collect {|x| x.copy }
UnifiedChain.new(links)
end
|
#theory_variables ⇒ Object
Returns an array of all the theory variables in the chain. All the theory variables should be global across the chain.
23
24
25
26
27
28
29
|
# File 'lib/UnifiedChain.rb', line 23
def theory_variables
results = @nodes.inject([]) do |total,theory|
total += theory.all_theory_variables.collect {|x| x}
total
end
return results.uniq
end
|
#valid_mapping?(runtime_method, test_cases, statement, mapping) ⇒ Boolean
293
294
295
296
297
|
# File 'lib/UnifiedChain.rb', line 293
def valid_mapping?(runtime_method,test_cases,statement,mapping)
intrinsic_statement = statement.map_to(mapping)
return false unless intrinsic_statement.select_all {|z| z.kind_of?(TheoryVariable)}.length == 0
valid_statement?(intrinsic_statement,runtime_method.copy,test_cases.copy)
end
|
#valid_mapping_permutations(runtime_method, test_cases) ⇒ Object
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
# File 'lib/UnifiedChain.rb', line 49
def valid_mapping_permutations(runtime_method,test_cases)
intrinsic_values = [IntrinsicRuntimeMethod.new,IntrinsicTestCases.new]
total_variables = self.theory_variables.length
available_values = [IntrinsicRuntimeMethod.new,IntrinsicTestCases.new]
valid_mappings = [Mapping.new]
itteration_limit = 9
@nodes.each_with_index do |node,index|
node.dependents.each do |dependent|
if index == 0
chain = partial_chain(0)
else
chain = partial_chain(index-1)
end
limit = 0
until has_all_variables_been_found?(dependent,valid_mappings) or limit > itteration_limit
valid_mappings = extend_mapping(valid_mappings,dependent,runtime_method.copy,test_cases.copy,chain,available_values)
limit += 1
end
end
unless node.action.nil?
if index == 0
chain = partial_chain(0)
else
chain = partial_chain(index-1)
end
limit = 0
until has_all_variables_been_found?(node.action,valid_mappings) or limit > itteration_limit
valid_mappings = extend_mapping(valid_mappings,node.action,runtime_method.copy,test_cases.copy,chain,available_values)
limit += 1
end
if limit > itteration_limit
pp missing_variables(node.action,valid_mappings)
raise StandardError.new('Unable to resolve action: '+"\n"+node.action.write)
end
end
node.results.each do |result|
chain = partial_chain(index)
limit = 0
until has_all_variables_been_found?(result,valid_mappings) or limit > itteration_limit
valid_mappings = extend_mapping(valid_mappings,result,runtime_method.copy,test_cases.copy,chain,available_values)
limit += 1
end
end
end
return valid_mappings.collect {|x| Mapping.new(x)}
end
|
#valid_statement?(statement, runtime_method, test_cases) ⇒ Boolean
303
304
305
306
307
308
|
# File 'lib/UnifiedChain.rb', line 303
def valid_statement?(statement,runtime_method,test_cases)
eval statement.write
return true
rescue NoMethodError
return false
end
|
#write(tab = 0) ⇒ Object
12
13
14
|
# File 'lib/UnifiedChain.rb', line 12
def write(tab=0)
return @nodes.inject('') {|total,x| total += x.write}
end
|