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,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