redshift 1.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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