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,100 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redshift'
4
+
5
+ include RedShift
6
+
7
+ # Substitutability of algebraic flows (i.e. flows have function semantics)
8
+ # Dependencies of diff/euler/alg on alg, and alg on diff.
9
+
10
+ class FlowTestComponent < Component
11
+ def finish test
12
+ end
13
+ end
14
+
15
+ class Flow_Sub < FlowTestComponent
16
+ s1 = "2*sin(u) + 1"
17
+ s2 = "pow(u, 2) + 3 * u"
18
+
19
+ f1 = proc { |v| s1.gsub(/u/,"(" + v + ")") }
20
+ f2 = proc { |v| s2.gsub(/u/,"(" + v + ")") }
21
+
22
+ flow {
23
+ diff "t' = 1"
24
+
25
+ alg "x = #{f1['t']}"
26
+ alg "xx = #{f2['x']}"
27
+
28
+ diff "y0' = #{f2[f1['t']]}"
29
+ diff "y1' = #{f2['x']}"
30
+ diff "y2' = xx"
31
+
32
+ euler "z0' = #{f2[f1['t']]}"
33
+ euler "z1' = #{f2['x']}"
34
+ euler "z2' = xx"
35
+ }
36
+ setup {
37
+ self.t = 0
38
+ self.y0 = self.y1 = self.y2 = self.z0 = self.z1 = self.z2 = 0
39
+ }
40
+ def assert_consistent test
41
+ str = "at time #{t}"
42
+ test.assert_in_delta(x, 2*sin(t) + 1, 0.000000001, str)
43
+ test.assert_in_delta(xx, (2*sin(t) + 1)**2 + 3 * (2*sin(t) + 1),
44
+ 0.000000001, str)
45
+
46
+ test.assert_in_delta(y0, y1, 0.000000001, str)
47
+ test.assert_in_delta(y0, y2, 0.000000001, str)
48
+
49
+ test.assert_in_delta(z0, z1, 0.000000001, str)
50
+ test.assert_in_delta(z0, z2, 0.000000001, str)
51
+ end
52
+ end
53
+
54
+
55
+ #-----#
56
+
57
+ require 'test/unit'
58
+
59
+ class TestFlow < Test::Unit::TestCase
60
+
61
+ def setup
62
+ @world = World.new
63
+ @world.time_step = 0.01
64
+ @world.zeno_limit = 100
65
+ end
66
+
67
+ def teardown
68
+ @world = nil
69
+ end
70
+
71
+ def test_flow
72
+ testers = []
73
+ ObjectSpace.each_object(Class) do |cl|
74
+ if cl <= FlowTestComponent and
75
+ cl.instance_methods.include? "assert_consistent"
76
+ testers << @world.create(cl)
77
+ end
78
+ end
79
+
80
+ testers.each { |t| t.assert_consistent self }
81
+ @world.run 1000 do
82
+ testers.each { |t| t.assert_consistent self }
83
+ end
84
+ testers.each { |t| t.finish self }
85
+ end
86
+ end
87
+
88
+ END {
89
+
90
+ # require 'plot/plot'
91
+ # Plot.new ('gnuplot') {
92
+ # add Flow_Reconfig::Y, 'title "y" with lines'
93
+ # add Flow_Reconfig::Y1, 'title "y1" with lines'
94
+ # add Flow_Reconfig::Y2, 'title "y2" with lines'
95
+ # add Flow_Reconfig::Y3, 'title "y3" with lines'
96
+ # show
97
+ # pause 5
98
+ # }
99
+
100
+ }
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redshift'
4
+ require 'sci/random'
5
+ require 'isaac'
6
+
7
+ # Adaptor class to use ISAAC with sci/random distributions.
8
+ class ISAACGenerator < ISAAC
9
+ def initialize(*seeds)
10
+ super()
11
+ if seeds.compact.empty?
12
+ seeds = [Random::Sequence.random_seed]
13
+ end
14
+ @seeds = seeds
15
+ srand(seeds)
16
+ end
17
+
18
+ attr_reader :seeds
19
+
20
+ alias next rand
21
+ end
22
+
23
+ include RedShift
24
+
25
+ class FlowTestComponent < Component
26
+ def finish test
27
+ end
28
+ end
29
+
30
+ # Shows that despite lazy eval of alg flows, they do get evaled before
31
+ # changing states.
32
+
33
+ class Flow_Transition_Alg_To_Other < FlowTestComponent
34
+ state :A, :B
35
+ start A
36
+ flow A do
37
+ alg "x=42"
38
+ end
39
+ transition A => B
40
+
41
+ def assert_consistent test
42
+ if state == B
43
+ test.assert_equal(42, x)
44
+ end
45
+ end
46
+ end
47
+
48
+ # state changes which change the type of flow
49
+
50
+ class Flow_Transition < FlowTestComponent
51
+ state :Alg, :Diff, :Euler, :Empty, :Switch
52
+
53
+ flow Alg, Diff, Euler, Empty do
54
+ diff "t' = 1"
55
+ end
56
+
57
+ flow Alg do
58
+ alg "x = 10*t"
59
+ end
60
+
61
+ flow Diff do
62
+ diff "x' = 10"
63
+ end
64
+
65
+ flow Euler do
66
+ euler "x' = 10"
67
+ end
68
+
69
+ setup do
70
+ self.x = 0
71
+ @alarm_time = 0
72
+ @alarm_seq = Random::Exponential.new \
73
+ :generator => ISAACGenerator,
74
+ :seed => nil, # 614822716,
75
+ :mean => 0.5
76
+ @state_seq = Random::Discrete.new \
77
+ :generator => ISAACGenerator,
78
+ :seed => nil, # 3871653669,
79
+ :distrib =>
80
+ {
81
+ Alg => 100,
82
+ Diff => 100,
83
+ Euler => 100,
84
+ Empty => 100
85
+ }
86
+ puts "\n\n Flow_Transition used the following seeds:"
87
+ puts " alarm seed = #{@alarm_seq.generator.seeds}"
88
+ puts " state seed = #{@state_seq.generator.seeds}"
89
+ end
90
+
91
+ transition Enter => Switch,
92
+ Alg => Switch, Diff => Switch,
93
+ Euler => Switch, Empty => Switch do
94
+ guard { t >= @alarm_time }
95
+ action {
96
+ # puts "Switching to #{@state_seq.next} at #{@alarm_time} sec."
97
+ # puts "x = #{x}, t = #{t}."
98
+ @alarm_time += @alarm_seq.next
99
+ @current = @state_seq.next
100
+ # puts " Next switch at #{@alarm_time} sec.\n\n"
101
+ ## unless we eval x here, the alg flow for x might not be up to date.
102
+ if (state == Empty)
103
+ @last_empty_t = t
104
+ self.x = 10 * t # manually update x
105
+ end
106
+ }
107
+ end
108
+
109
+ transition Switch => Alg do
110
+ guard { @current == Alg }
111
+ end
112
+ transition Switch => Diff do
113
+ guard { @current == Diff }
114
+ end
115
+ transition Switch => Euler do
116
+ guard { @current == Euler }
117
+ end
118
+ transition Switch => Empty do
119
+ guard { @current == Empty }
120
+ end
121
+
122
+ transition Empty => Empty do
123
+ guard { t > (@last_empty_t || 0) }
124
+ action {
125
+ @last_empty_t = t
126
+ self.x = 10 * t # manually update x
127
+ }
128
+ end
129
+
130
+ def assert_consistent test
131
+ # In the alg case, calling the accessor invokes the update method. We want
132
+ # to test that alg flows work even if the update method isn't called.
133
+ unless state == Alg
134
+ test.assert_in_delta(
135
+ 10 * t,
136
+ x,
137
+ 0.00000000001,
138
+ "in #{state.name} after #{t} sec,\n")
139
+ end
140
+ end
141
+
142
+ def finish test
143
+ # puts "At finish: t = #{t}, alarm_time = #{@alarm_time}"
144
+ end
145
+ end
146
+
147
+
148
+ # After changing out of a state with an alg flow, the variable should
149
+ # have a value defined by that flow, even if the flow was never
150
+ # explicitly referenced. Check that the strict optimization doesn't
151
+ # interfere with this evaluation.
152
+ class Flow_LeavingAlgebraic < FlowTestComponent
153
+ continuous :x
154
+ strictly_continuous :y
155
+ state :S, :T
156
+ flow S do
157
+ alg " x = 42 "
158
+ alg " y = 43 "
159
+ end
160
+ transition Enter => S, S => T
161
+ def assert_consistent test
162
+ if state == T
163
+ test.assert_equal(42, x)
164
+ test.assert_equal(43, y)
165
+ end
166
+ end
167
+ end
168
+
169
+
170
+ # Test what happens when a transition changes the algebraic flow of a variable
171
+
172
+ class Flow_AlgToAlg < FlowTestComponent
173
+ state :A, :B
174
+ flow A, B do diff "t' = 1" end
175
+ flow A do alg "x = 1" end
176
+ flow B do alg "x = 2" end
177
+ start A
178
+ transition A => B do
179
+ guard "t > 0.2"
180
+ action do
181
+ @snapshotA = x
182
+ end
183
+ end
184
+ transition B => B do
185
+ guard {!@snapshotB}
186
+ action do
187
+ @snapshotB = x
188
+ end
189
+ end
190
+ def assert_consistent test
191
+ return if t > 0.4 ## should be a way to remove this component
192
+ case state
193
+ when A; test.assert_equal(1, x)
194
+ when B; test.assert_equal(2, x)
195
+ test.assert_equal(1, @snapshotA)
196
+ test.assert_equal(2, @snapshotB)
197
+ end
198
+ end
199
+ end
200
+
201
+ # Test what happens during an action when an algebraic flow's inputs change.
202
+ # The alg flow's value *does* change during the action, if there are changes
203
+ # in any of the links, continuous vars, or constants that it depends on.
204
+
205
+ class Flow_AlgebraicAction < FlowTestComponent
206
+ continuous :x, :y
207
+ constant :k
208
+ link :other => self
209
+ flow {alg " x = other.y + k "}
210
+
211
+ @@first = true
212
+
213
+ setup do
214
+ self.other = self
215
+ if @@first
216
+ @@first = false
217
+ @other = create(Flow_AlgebraicAction) {|c| c.y = 5}
218
+ end
219
+ end
220
+
221
+ transition Enter => Exit do
222
+ action do
223
+ next unless @other
224
+
225
+ @x_values = []
226
+ @x_values << x
227
+ other.y = 1
228
+ @x_values << x
229
+ other.y = 2
230
+ @x_values << x
231
+
232
+ self.other = @other
233
+ @x_values << x
234
+
235
+ self.k = 10
236
+ @x_values << x
237
+ end
238
+ end
239
+
240
+ def assert_consistent test
241
+ test.assert_equal([0,1,2,5,15], @x_values) if @x_values
242
+ end
243
+ end
244
+
245
+
246
+ #-----#
247
+
248
+ require 'test/unit'
249
+
250
+ class TestFlow < Test::Unit::TestCase
251
+
252
+ def setup
253
+ @world = World.new
254
+ @world.time_step = 0.01
255
+ @world.zeno_limit = 100
256
+ end
257
+
258
+ def teardown
259
+ @world = nil
260
+ end
261
+
262
+ def test_flow
263
+ testers = []
264
+ ObjectSpace.each_object(Class) do |cl|
265
+ if cl <= FlowTestComponent and
266
+ cl.instance_methods.include? "assert_consistent"
267
+ testers << @world.create(cl)
268
+ end
269
+ end
270
+
271
+ testers.each { |t| t.assert_consistent self }
272
+ @world.run 1000 do
273
+ testers.each { |t| t.assert_consistent self }
274
+ # testers.reject! { |t| t.state == Exit }
275
+ end
276
+ testers.each { |t| t.finish self }
277
+ end
278
+ end
279
+
280
+ END {
281
+
282
+ # require 'plot/plot'
283
+ # Plot.new ('gnuplot') {
284
+ # add Flow_Reconfig::Y, 'title "y" with lines'
285
+ # add Flow_Reconfig::Y1, 'title "y1" with lines'
286
+ # add Flow_Reconfig::Y2, 'title "y2" with lines'
287
+ # add Flow_Reconfig::Y3, 'title "y3" with lines'
288
+ # show
289
+ # pause 5
290
+ # }
291
+
292
+ }
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redshift'
4
+
5
+ include RedShift
6
+
7
+ =begin
8
+
9
+ =test_inherit.rb
10
+
11
+ One big, complex test class hierarchy, for testing mixed features.
12
+
13
+ =end
14
+
15
+ class A < Component
16
+
17
+ attr_accessor :t
18
+
19
+ state :S0, :S1, :S2
20
+
21
+ setup { start S0; @x = -100000; @t = 0 } # To override
22
+
23
+ flow(S0, S1, S2) { diff "t' = 1" }
24
+
25
+ flow(S0) { diff "x' = 1" }
26
+ flow(S1) { diff "x' = -10" } # To override
27
+ flow(S2) { diff "x' = 100" }
28
+
29
+ transition S0 => S1 do guard { @t > 1 }; action { @t -= 1 } end
30
+
31
+ # To override:
32
+ transition(S1 => S2) {
33
+ name :from_S1_to_S2 # so that inheritance knows what to replace
34
+ guard { @t > 0.5 }; action { puts "KABOOM!" }
35
+ }
36
+
37
+ end
38
+
39
+ class B < A
40
+
41
+ state :S3
42
+
43
+ setup { @x = 0 }
44
+
45
+ flow(S1) { diff "x' = -20" } # To override
46
+ flow(S3) { diff "x' = 1000", "t' = 1" }
47
+
48
+ transition(S1 => S2) {
49
+ name :from_S1_to_S2
50
+ guard { @t > 1 }; action { @t -= 1 }
51
+ }
52
+
53
+ transition(S2 => S3) { guard { @t > 1 }; action { @t -= 1 } }
54
+
55
+ end
56
+
57
+ class C < B
58
+
59
+ state :S4
60
+
61
+ flow(S1) { diff "x' = 10" }
62
+ flow(S4) { diff "x' = 10000", "t' = 1" }
63
+
64
+ transition(S3 => S4) { guard { @t > 1 }; action { @t -= 1 } }
65
+
66
+ end
67
+
68
+ class Z < Component
69
+
70
+ attr_accessor :t
71
+
72
+ state :S0, :S1, :S2, :S3, :S4
73
+
74
+ setup { start S0; @x = 0; @t = 0 }
75
+
76
+ flow(S0, S1, S2, S3, S4) { diff "t' = 1" }
77
+
78
+ flow(S0) { diff "x' = 1" }
79
+ flow(S1) { diff "x' = 10" }
80
+ flow(S2) { diff "x' = 100" }
81
+ flow(S3) { diff "x' = 1000" }
82
+ flow(S4) { diff "x' = 10000" }
83
+
84
+ transition(S0 => S1) { guard { @t > 1 }; action { @t -= 1 } }
85
+ transition(S1 => S2) { guard { @t > 1 }; action { @t -= 1 } }
86
+ transition(S2 => S3) { guard { @t > 1 }; action { @t -= 1 } }
87
+ transition(S3 => S4) { guard { @t > 1 }; action { @t -= 1 } }
88
+
89
+ end
90
+
91
+
92
+ require 'test/unit'
93
+
94
+ class TestInherit < Test::Unit::TestCase
95
+
96
+ def setup
97
+ @world = World.new
98
+ @world.time_step = 0.1
99
+ end
100
+
101
+ def teardown
102
+ @world = nil
103
+ end
104
+
105
+ def test_mixed
106
+ c = @world.create(C)
107
+ z = @world.create(Z)
108
+
109
+ # Static assertions
110
+ c_state_names = c.states.map {|s| s.name}
111
+ z_state_names = z.states.map {|s| s.name}
112
+ assert_equal([], c_state_names - z_state_names)
113
+ assert_equal([], z_state_names - c_state_names)
114
+
115
+ # Dynamic assertions
116
+ while @world.clock <= 10 do
117
+ @world.run
118
+
119
+ assert_equal(c.t, z.t,
120
+ "time #{@world.clock}\n")
121
+ assert_equal(c.state.name, z.state.name,
122
+ "time #{@world.clock}\n c.t: #{c.t} z.t: #{z.t}")
123
+
124
+ assert_in_delta(c.x, z.x, 0.000001)
125
+ end
126
+ end
127
+ end