redshift 1.3.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. data/.gitignore +8 -0
  2. data/README +5 -0
  3. data/RELEASE-NOTES +455 -0
  4. data/TODO +431 -0
  5. data/bench/alg-state.rb +61 -0
  6. data/bench/bench +26 -0
  7. data/bench/bench.rb +10 -0
  8. data/bench/continuous.rb +76 -0
  9. data/bench/diff-bench +86 -0
  10. data/bench/discrete.rb +101 -0
  11. data/bench/euler.rb +50 -0
  12. data/bench/formula.rb +78 -0
  13. data/bench/half-strict.rb +103 -0
  14. data/bench/inertness.rb +116 -0
  15. data/bench/queue.rb +92 -0
  16. data/bench/run +66 -0
  17. data/bench/simple.rb +74 -0
  18. data/bench/strictness.rb +86 -0
  19. data/examples/ball-tkar.rb +72 -0
  20. data/examples/ball.rb +123 -0
  21. data/examples/collide.rb +70 -0
  22. data/examples/connect-parallel.rb +48 -0
  23. data/examples/connect.rb +109 -0
  24. data/examples/constants.rb +27 -0
  25. data/examples/delay.rb +80 -0
  26. data/examples/derivative.rb +77 -0
  27. data/examples/euler.rb +46 -0
  28. data/examples/external-lib.rb +33 -0
  29. data/examples/guard-debugger.rb +77 -0
  30. data/examples/lotka-volterra.rb +33 -0
  31. data/examples/persist-ball.rb +68 -0
  32. data/examples/pid.rb +87 -0
  33. data/examples/ports.rb +60 -0
  34. data/examples/queue.rb +56 -0
  35. data/examples/queue2.rb +98 -0
  36. data/examples/reset-with-event-val.rb +28 -0
  37. data/examples/scheduler.rb +104 -0
  38. data/examples/set-dest.rb +23 -0
  39. data/examples/simulink/README +1 -0
  40. data/examples/simulink/delay.mdl +827 -0
  41. data/examples/simulink/derivative.mdl +655 -0
  42. data/examples/step-discrete-profiler.rb +103 -0
  43. data/examples/subsystem.rb +109 -0
  44. data/examples/sync-deadlock.rb +32 -0
  45. data/examples/sync-queue.rb +91 -0
  46. data/examples/sync-retry.rb +20 -0
  47. data/examples/sync.rb +51 -0
  48. data/examples/thermostat.rb +53 -0
  49. data/examples/zeno.rb +53 -0
  50. data/lib/accessible-index.rb +47 -0
  51. data/lib/redshift.rb +1 -0
  52. data/lib/redshift/component.rb +412 -0
  53. data/lib/redshift/meta.rb +183 -0
  54. data/lib/redshift/mixins/zeno-debugger.rb +69 -0
  55. data/lib/redshift/port.rb +57 -0
  56. data/lib/redshift/queue.rb +104 -0
  57. data/lib/redshift/redshift.rb +111 -0
  58. data/lib/redshift/state.rb +31 -0
  59. data/lib/redshift/syntax.rb +558 -0
  60. data/lib/redshift/target/c.rb +37 -0
  61. data/lib/redshift/target/c/component-gen.rb +1303 -0
  62. data/lib/redshift/target/c/flow-gen.rb +325 -0
  63. data/lib/redshift/target/c/flow/algebraic.rb +85 -0
  64. data/lib/redshift/target/c/flow/buffer.rb +74 -0
  65. data/lib/redshift/target/c/flow/delay.rb +203 -0
  66. data/lib/redshift/target/c/flow/derivative.rb +101 -0
  67. data/lib/redshift/target/c/flow/euler.rb +67 -0
  68. data/lib/redshift/target/c/flow/expr.rb +113 -0
  69. data/lib/redshift/target/c/flow/rk4.rb +80 -0
  70. data/lib/redshift/target/c/library.rb +85 -0
  71. data/lib/redshift/target/c/world-gen.rb +1370 -0
  72. data/lib/redshift/target/spec.rb +34 -0
  73. data/lib/redshift/world.rb +300 -0
  74. data/rakefile +37 -0
  75. data/test/test.rb +52 -0
  76. data/test/test_buffer.rb +58 -0
  77. data/test/test_connect.rb +242 -0
  78. data/test/test_connect_parallel.rb +47 -0
  79. data/test/test_connect_strict.rb +135 -0
  80. data/test/test_constant.rb +74 -0
  81. data/test/test_delay.rb +145 -0
  82. data/test/test_derivative.rb +48 -0
  83. data/test/test_discrete.rb +592 -0
  84. data/test/test_discrete_isolated.rb +92 -0
  85. data/test/test_exit.rb +59 -0
  86. data/test/test_flow.rb +200 -0
  87. data/test/test_flow_link.rb +288 -0
  88. data/test/test_flow_sub.rb +100 -0
  89. data/test/test_flow_trans.rb +292 -0
  90. data/test/test_inherit.rb +127 -0
  91. data/test/test_inherit_event.rb +74 -0
  92. data/test/test_inherit_flow.rb +139 -0
  93. data/test/test_inherit_link.rb +65 -0
  94. data/test/test_inherit_setup.rb +56 -0
  95. data/test/test_inherit_state.rb +66 -0
  96. data/test/test_inherit_transition.rb +168 -0
  97. data/test/test_numerics.rb +34 -0
  98. data/test/test_queue.rb +90 -0
  99. data/test/test_queue_alone.rb +115 -0
  100. data/test/test_reset.rb +209 -0
  101. data/test/test_setup.rb +119 -0
  102. data/test/test_strict_continuity.rb +410 -0
  103. data/test/test_strict_reset_error.rb +30 -0
  104. data/test/test_strictness_error.rb +32 -0
  105. data/test/test_sync.rb +185 -0
  106. data/test/test_world.rb +328 -0
  107. metadata +204 -0
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redshift'
4
+
5
+ include RedShift
6
+
7
+ require 'test/unit'
8
+
9
+ # See also test_strict_continuity.rb.
10
+
11
+ class TestStrictnessError < Test::Unit::TestCase
12
+
13
+ class T < Component
14
+
15
+ strictly_continuous :x
16
+
17
+ transition do
18
+ reset :x => 1
19
+ end
20
+
21
+ end
22
+
23
+ # This is the only test that can appear in this file.
24
+ def test_strict_reset_error
25
+ assert_raises(RedShift::StrictnessError) do
26
+ World.new
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redshift'
4
+
5
+ include RedShift
6
+
7
+ require 'test/unit'
8
+
9
+ # See also test_strict_continuity.rb.
10
+
11
+ class TestStrictnessError < Test::Unit::TestCase
12
+
13
+ class T < Component
14
+
15
+ strictly_continuous :x
16
+ continuous :y
17
+ link :lnk => T
18
+
19
+ flow {
20
+ alg "x = lnk.y+1"
21
+ }
22
+
23
+ end
24
+
25
+ # This is the only test that can appear in this file.
26
+ def test_strictness_error
27
+ assert_raises(RedShift::StrictnessError) do
28
+ World.new
29
+ end
30
+ end
31
+
32
+ end
data/test/test_sync.rb ADDED
@@ -0,0 +1,185 @@
1
+ # test chains of asymmetric sync
2
+ # when guard not enabled at root, ...
3
+
4
+ # test chains of symmetric sync
5
+
6
+ require 'redshift'
7
+ require 'test/unit'
8
+
9
+ class DebugSyncWorld #< RedShift::World
10
+ def hook_begin
11
+ puts "===== begin discrete update ====="
12
+ end
13
+
14
+ def hook_enter_sync_phase
15
+ puts "enter sync phase"
16
+ end
17
+
18
+ def hook_can_sync comp, can_sync
19
+ puts " #{comp.inspect}: can_sync=#{can_sync.inspect}"
20
+ end
21
+
22
+ def hook_sync_step syncers, changed
23
+ puts " sync step, changed=#{changed.inspect}"
24
+ puts " syncers = #{syncers.inspect}"
25
+ end
26
+ end
27
+
28
+ class TestSync < Test::Unit::TestCase
29
+ class Relay < RedShift::Component
30
+ link :next
31
+
32
+ transition Enter => Exit do
33
+ sync :next => :e
34
+ event :e
35
+ end
36
+ end
37
+
38
+ class Emitter < RedShift::Component
39
+ transition Enter => Exit do
40
+ event :e
41
+ end
42
+ end
43
+
44
+ class Emitter_f < RedShift::Component
45
+ transition Enter => Exit do
46
+ event :f
47
+ end
48
+ end
49
+
50
+ class Ground < RedShift::Component
51
+ link :next
52
+
53
+ transition Enter => Exit do
54
+ sync :next => :e
55
+ end
56
+ end
57
+
58
+ class EmitTwo < RedShift::Component
59
+ state :EmitE, :EmitF, :EmitEF
60
+ transition Enter => EmitE do
61
+ event :e
62
+ end
63
+ transition EmitE => EmitF do
64
+ event :f
65
+ end
66
+ transition EmitF => EmitEF do
67
+ event :e, :f
68
+ end
69
+ end
70
+
71
+ class SyncTwo < RedShift::Component
72
+ link :next
73
+ setup {self.next = create(EmitTwo)}
74
+ transition Enter => Exit do
75
+ sync :next => :e
76
+ sync :next => :f
77
+ action do
78
+ @worked = (self.next.state == EmitTwo::EmitF)
79
+ end
80
+ end
81
+ attr_reader :worked
82
+ end
83
+
84
+ class SyncRetry < RedShift::Component
85
+ state :Ok
86
+ link :next
87
+ setup {self.next = nil}
88
+ transition Enter => Exit do
89
+ sync :next => :no_such_event
90
+ end
91
+ transition Enter => Ok
92
+ end
93
+
94
+ def setup
95
+ @w = RedShift::World.new
96
+ end
97
+
98
+ def test_sync_self
99
+ r = @w.create Relay
100
+ r.next = r
101
+ g = @w.create Ground
102
+ @w.run 1
103
+ assert_equal(RedShift::Component::Exit, r.state)
104
+ assert_equal(RedShift::Component::Enter, g.state)
105
+ end
106
+
107
+ def test_sync_nil
108
+ r = @w.create Relay
109
+ r.next = nil
110
+ @w.run 1
111
+ assert_equal(RedShift::Component::Enter, r.state)
112
+ end
113
+
114
+ def test_sync_no_event
115
+ r = @w.create Relay
116
+ r.next = @w.create Relay
117
+ @w.run 10
118
+ assert_equal(RedShift::Component::Enter, r.state)
119
+ end
120
+
121
+ def test_sync_wrong_event
122
+ r = @w.create Relay
123
+ r.next = @w.create Emitter_f
124
+ @w.run 10
125
+ assert_equal(RedShift::Component::Enter, r.state)
126
+ end
127
+
128
+ def test_sync_two_events
129
+ s2 = @w.create(SyncTwo)
130
+ assert_equal(nil, s2.worked)
131
+ @w.run 1
132
+ assert_equal(true, s2.worked)
133
+ end
134
+
135
+ def test_cyclic
136
+ a = (0..4).map do
137
+ @w.create Relay
138
+ end
139
+
140
+ # connect them in an order different from creation order
141
+ a[4].next = a[3]
142
+ a[3].next = a[1]
143
+ a[1].next = a[2]
144
+ a[2].next = a[0]
145
+ a[0].next = a[4]
146
+
147
+ @w.run 1
148
+ a.each do |relay|
149
+ assert_equal(RedShift::Component::Exit, relay.state)
150
+ end
151
+ end
152
+
153
+ def test_acyclic
154
+ a = (0..4).map do
155
+ @w.create Relay
156
+ end
157
+
158
+ # connect them in an order different from creation order
159
+ a[4].next = a[3]
160
+ a[3].next = a[1]
161
+ a[1].next = a[2]
162
+ a[2].next = a[0]
163
+ a[0].next = nil
164
+
165
+ @w.run 1
166
+ a.each do |relay|
167
+ assert_equal(RedShift::Component::Enter, relay.state)
168
+ end
169
+
170
+ emitter = @w.create Emitter
171
+ a[0].next = emitter
172
+
173
+ @w.run 1
174
+ (a + [emitter]).each do |relay|
175
+ assert_equal(RedShift::Component::Exit, relay.state)
176
+ end
177
+ end
178
+
179
+ # see also examples/sync-retry.rb
180
+ def test_sync_retry
181
+ c = @w.create SyncRetry
182
+ @w.run 1
183
+ assert_equal(SyncRetry::Ok, c.state)
184
+ end
185
+ end
@@ -0,0 +1,328 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redshift'
4
+
5
+ include RedShift
6
+
7
+ # test setup and default clauses in world class and in world instance
8
+ # test World#started?
9
+
10
+ class World_1 < World
11
+ default { @d = 6 }
12
+ setup { @x = 1 }; setup { @y = 2 }
13
+ def initialize
14
+ super {
15
+ @e = @d + 1
16
+ @z = 3
17
+ }
18
+ setup { @t = 4 }; setup { @u = 5 }
19
+ end
20
+ def assert_consistent_before test
21
+ test.assert(!started?)
22
+ test.assert_equal([nil,nil,3,nil,nil,6,7], [@x,@y,@z,@t,@u,@d,@e])
23
+ end
24
+ def assert_consistent_after test
25
+ test.assert(started?)
26
+ test.assert_equal([1,2,3,4,5,6,7], [@x,@y,@z,@t,@u,@d,@e])
27
+ end
28
+ end
29
+
30
+ # test inheritance of setup clauses
31
+
32
+ class World_1_1 < World_1
33
+ setup { @y = 2.1; @r = 6 }
34
+ def initialize
35
+ super
36
+ setup { @u = 5.1; @s = 7 }
37
+ end
38
+ def assert_consistent_before test
39
+ test.assert_equal([nil,nil,3,nil,nil,nil,nil], [@x,@y,@z,@t,@u,@r,@s])
40
+ end
41
+ def assert_consistent_after test
42
+ test.assert_equal([1,2.1,3,4,5.1,6,7], [@x,@y,@z,@t,@u,@r,@s])
43
+ end
44
+ end
45
+
46
+ # test world clock, time step, clock start, clock finish
47
+
48
+ class World_2 < World
49
+ class Timer < Component
50
+ flow {diff "t' = 1"}
51
+ end
52
+
53
+ def run
54
+ super 1_000_000
55
+ end
56
+
57
+ def initialize
58
+ super do
59
+ self.time_step = 1.01
60
+ self.clock_start = 90.001
61
+ self.clock_finish = 100
62
+ end
63
+
64
+ setup do
65
+ @timer = create(Timer) {|timer| timer.t = 90.001}
66
+ end
67
+ end
68
+
69
+ def assert_consistent_before test
70
+ test.assert_equal(90.001, clock)
71
+ end
72
+ def assert_consistent_after test
73
+ test.assert_in_delta(@timer.t, clock, 1.0E-13)
74
+ test.assert_equal(100.101, clock)
75
+ end
76
+ end
77
+
78
+ # test integer time step
79
+
80
+ class World_2_1 < World_2
81
+ def initialize
82
+ super
83
+ self.time_step = 5
84
+ end
85
+ def assert_consistent_before test
86
+ test.assert_equal(90.001, clock)
87
+ end
88
+ def assert_consistent_after test
89
+ test.assert_in_delta(@timer.t, clock, 1.0E-13)
90
+ test.assert_equal(100.001, clock)
91
+ end
92
+ end
93
+
94
+ # test create and remove
95
+
96
+ puts "World#remove TEST DISABLED **************************"
97
+ if false && World.instance_methods.include?("remove")
98
+ class World_3 < World
99
+ setup do @x = create(Component) end
100
+ def run
101
+ super
102
+ remove @x
103
+ end
104
+
105
+ def assert_consistent_after test
106
+ test.assert_equal(0, size)
107
+ end
108
+ end
109
+ end
110
+
111
+ # test garbage collection
112
+
113
+ puts "GC TEST DISABLED **************************"
114
+ if false
115
+ class World_4 < World
116
+ setup do
117
+ @x = create(Component)
118
+ 5.times do create(Component) end
119
+ end
120
+
121
+ def run
122
+ super
123
+ @before_size = size
124
+ garbage_collect
125
+ @after_size = size
126
+ end
127
+
128
+ def assert_consistent_after test
129
+ test.assert_equal(6, @before_size)
130
+ test.assert_equal(1, @after_size)
131
+ end
132
+ end
133
+ end
134
+
135
+ # test zeno detection
136
+
137
+ class World_5 < World
138
+ class Zeno < Component
139
+ transition Enter => Enter
140
+ end
141
+
142
+ setup do create(Zeno) end
143
+
144
+ def initialize
145
+ super
146
+ self.zeno_limit = 100
147
+ end
148
+
149
+ def step_zeno
150
+ @zeno_step_reached = true
151
+ super # raise ZenoError
152
+ end
153
+
154
+ def run
155
+ super
156
+ rescue => @e
157
+ end
158
+
159
+ def assert_consistent_after test
160
+ test.assert_kind_of(ZenoError, @e)
161
+ test.assert(@zeno_step_reached)
162
+ end
163
+ end
164
+
165
+ # test "run 0"
166
+
167
+ class World_6 < World
168
+ class Thing < Component
169
+ state :A, :B
170
+ default do
171
+ start A
172
+ @x = 0
173
+ end
174
+ flow A do
175
+ diff "x' = 1"
176
+ end
177
+ transition A => B do
178
+ guard {x < 0} # won't happen normally
179
+ end
180
+ end
181
+
182
+ setup {@thing = create Thing}
183
+
184
+ def run
185
+ super 0 ## do_setup and step_discrete -- test this
186
+ super 1
187
+ super 0 ## should do nothing -- repeat and test this
188
+ @thing.x = -1 # enables a guard
189
+ super 0
190
+ end
191
+
192
+ def assert_consistent_before test
193
+ test.assert_equal(0, size)
194
+ end
195
+ def assert_consistent_after test
196
+ test.assert_equal(1, size)
197
+ test.assert_equal(Thing::B, @thing.state)
198
+ end
199
+ end
200
+
201
+ # test persistence
202
+
203
+ class World_7 < World
204
+ def make_copy
205
+ filename = File.join($REDSHIFT_WORK_DIR, $REDSHIFT_CLIB_NAME,
206
+ "test_world_persist.dat")
207
+ save(filename)
208
+ World.open(filename) # copy of world (with the same name)
209
+ ensure
210
+ # File.delete(filename) rescue SystemCallError
211
+ end
212
+
213
+ class Thing < Component
214
+ attr_reader :x_start
215
+ state :A, :B, :C; default {start A}
216
+ setup do
217
+ @x_start = self.x = 123
218
+ end
219
+ transition A => B
220
+ transition B => C do
221
+ guard { x > 200 }
222
+ end
223
+ flow B, C do
224
+ diff "x' = 1"
225
+ end
226
+ end
227
+
228
+ attr_accessor :thing
229
+
230
+ setup do
231
+ @thing = create Thing
232
+ end
233
+
234
+ def run n = nil
235
+ if n
236
+ super n
237
+ else
238
+ @start_copy = make_copy
239
+ super 0 # do_setup and step_discrete
240
+ @t0_copy = make_copy
241
+ super 1 # run the same world after saving
242
+ @t1_copy = make_copy
243
+ super 999
244
+ @t1000_copy = make_copy
245
+ end
246
+ end
247
+
248
+ def assert_consistent_after test
249
+ test.assert_equal(nil, @start_copy.thing)
250
+ test.assert_equal(Thing::B, @t0_copy.thing.state)
251
+ test.assert_equal(Thing::B, @t1_copy.thing.state)
252
+ test.assert_equal(Thing::C, @t1000_copy.thing.state)
253
+ test.assert_equal(Thing::C, thing.state)
254
+
255
+ other_thing = create Thing
256
+
257
+ test.assert_equal(thing.x_start, @t0_copy.thing.x_start)
258
+ test.assert_equal(thing.x_start, @t1_copy.thing.x_start)
259
+ test.assert_equal(thing.x_start, @t1000_copy.thing.x_start)
260
+ test.assert_equal(thing.x_start, thing.x_start)
261
+
262
+ x_t0 = thing.x_start
263
+ x_t1 = thing.x_start + time_step
264
+ x_t1000 = thing.x_start + 1000 * time_step
265
+
266
+ test.assert_in_delta(x_t0, @t0_copy.thing.x, 1E-10)
267
+ test.assert_in_delta(x_t1, @t1_copy.thing.x, 1E-10)
268
+ test.assert_in_delta(x_t1000, @t1000_copy.thing.x, 1E-10)
269
+ test.assert_in_delta(x_t1000, thing.x, 1E-10)
270
+
271
+ # continue running with @t1_copy
272
+ @t1_copy.run 999
273
+ test.assert_equal(Thing::C, @t1_copy.thing.state)
274
+ test.assert_in_delta(x_t1000, @t1_copy.thing.x, 1E-10)
275
+ end
276
+ end
277
+
278
+ =begin
279
+
280
+ tests:
281
+ can you set time step et al during setup? No. Should this be allowed?
282
+ run methods, debug tools
283
+
284
+ =end
285
+
286
+ #-----#
287
+
288
+ require 'test/unit'
289
+
290
+ class TestWorld < Test::Unit::TestCase
291
+
292
+ def test_world
293
+ testers = []
294
+ ObjectSpace.each_object(Class) do |cl|
295
+ if cl <= World and ## cl.instance_methods.grep /\Aassert_consistent/
296
+ (cl.instance_methods.include? "assert_consistent_before" or
297
+ cl.instance_methods.include? "assert_consistent_after")
298
+ testers << cl.new
299
+ end
300
+ end
301
+
302
+ for t in testers
303
+ t.assert_consistent_before self if t.respond_to? :assert_consistent_before
304
+ t.run
305
+ t.assert_consistent_after self if t.respond_to? :assert_consistent_after
306
+ end
307
+ end
308
+
309
+ def test_var_time_step
310
+ w = World.new
311
+
312
+ w.time_step = 0.01
313
+ w.evolve 1.0
314
+ assert_in_delta(1.0, w.clock, 1.0e-9)
315
+
316
+ w.time_step = 0.1
317
+ w.evolve 1.0
318
+ assert_in_delta(2.0, w.clock, 1.0e-9)
319
+
320
+ w.time_step = 0.05
321
+ w.evolve 1.0
322
+ assert_in_delta(3.0, w.clock, 1.0e-9)
323
+
324
+ w.time_step = 0.25
325
+ w.evolve 1.0
326
+ assert_in_delta(4.0, w.clock, 1.0e-9)
327
+ end
328
+ end