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,242 @@
1
+ require "redshift"
2
+ include RedShift
3
+
4
+ class A < Component
5
+ continuous :x
6
+ constant :k => 6.78
7
+ flow do
8
+ diff " x' = 2*x "
9
+ end
10
+ end
11
+
12
+ class B < Component
13
+ input :y
14
+ input :yy # usually unused, so doesn't need to be connected
15
+ link :other => B
16
+
17
+ flow do
18
+ alg " z = y+1 "
19
+ alg " w = y + yy "
20
+ alg " u = other.y "
21
+ end
22
+ transition Enter => Exit do
23
+ guard "y < 0"
24
+ end
25
+ end
26
+
27
+ #-----#
28
+
29
+ require 'test/unit'
30
+
31
+ class TestConnect < Test::Unit::TestCase
32
+
33
+ def setup
34
+ @world = World.new
35
+ @world.time_step = 0.1
36
+ @a = @world.create(A)
37
+ @b = @world.create(B)
38
+ end
39
+
40
+ def teardown
41
+ @world = nil
42
+ end
43
+
44
+ def test_unconnected
45
+ assert_raises(UnconnectedInputError) do
46
+ @b.y
47
+ end
48
+
49
+ assert_raises(NoMethodError) do
50
+ @b.y = 1.23
51
+ end
52
+
53
+ assert_raises(UnconnectedInputError) do
54
+ @world.evolve 1
55
+ end
56
+
57
+ assert_raises(UnconnectedInputError) do
58
+ @b.z
59
+ end
60
+ end
61
+
62
+ def test_not_connectable
63
+ assert_raises(TypeError) do
64
+ @a.port(:x) << @b.port(:y)
65
+ end
66
+ assert_raises(TypeError) do
67
+ @a.connect(:x, @b, :y)
68
+ end
69
+ end
70
+
71
+ def test_connect
72
+ @b.connect(:y, @a, :x)
73
+ @a.x = 4.56
74
+
75
+ assert_equal(@a.x, @b.y)
76
+ assert_equal(@b.y+1, @b.z)
77
+ @world.evolve 1 do
78
+ assert_equal(@a.x, @b.y)
79
+ assert_equal(@b.y+1, @b.z)
80
+ end
81
+
82
+ # reconnect to different var (actually a constant)
83
+ @b.connect(:y, @a, :k)
84
+
85
+ assert_equal(@a.k, @b.y)
86
+ assert_equal(@b.y+1, @b.z)
87
+ @world.evolve 1 do
88
+ assert_equal(@a.k, @b.y)
89
+ assert_equal(@b.y+1, @b.z)
90
+ end
91
+
92
+ # disconnect
93
+ @b.disconnect(:y)
94
+
95
+ assert_raises(UnconnectedInputError) do
96
+ @b.z
97
+ end
98
+
99
+ assert_raises(UnconnectedInputError) do
100
+ @b.y
101
+ end
102
+
103
+ # nothing raised:
104
+ @b.disconnect(:y)
105
+
106
+ # reconnect to different component (using ports)
107
+ @a = @world.create(A)
108
+ @b.port(:y) << @a.port(:x)
109
+
110
+ @a.x = 7.89
111
+
112
+ assert_equal(@a.x, @b.y)
113
+ assert_equal(@a.x, @b.port(:y).value)
114
+ assert_equal(@b.y+1, @b.z)
115
+ @world.evolve 1 do
116
+ assert_equal(@a.x, @b.y)
117
+ assert_equal(@b.y+1, @b.z)
118
+ end
119
+ end
120
+
121
+ def test_reflection
122
+ @b.connect(:y, @a, :x)
123
+
124
+ assert_equal(@a.port(:x), @b.port(:y).source)
125
+ assert_equal(@a, @b.port(:y).source_component)
126
+ assert_equal(:x, @b.port(:y).source_variable)
127
+
128
+ assert_equal(@a, @a.port(:x).component)
129
+ assert_equal(:x, @a.port(:x).variable)
130
+ end
131
+
132
+ def test_disconnect
133
+ @b.connect(:y, @a, :x)
134
+ @b.disconnect(:y)
135
+ assert_equal(nil, @b.port(:y).source)
136
+
137
+ @b.port(:y).disconnect
138
+ assert_equal(nil, @b.port(:y).source)
139
+
140
+ @b.port(:y) << nil
141
+ assert_equal(nil, @b.port(:y).source)
142
+
143
+ assert_raises(UnconnectedInputError) do
144
+ @b.y
145
+ end
146
+ end
147
+
148
+ def test_connect_to_input
149
+ b2 = @world.create(B)
150
+ @b.port(:y) << @a.port(:x)
151
+ b2.port(:y) << @b.port(:y)
152
+ @a.x = 3.456
153
+ assert_equal(@b.y, b2.y)
154
+ assert_equal(@a.x, b2.y)
155
+ assert_equal(b2.y+1, b2.z)
156
+ end
157
+
158
+ def test_connect_input_chain
159
+ b = (0..99).map {@world.create(B)}
160
+ (0..98).each do |i|
161
+ b[i+1].port(:y) << b[i].port(:y)
162
+ end
163
+ b[0].port(:y) << @a.port(:x)
164
+
165
+ @a.x = 42.4242
166
+ assert_equal(@a.x, b[99].y)
167
+ assert_equal(@a.x, b[0].y)
168
+
169
+ old_b_50 = b[50]
170
+ b[50] = @world.create(B)
171
+ b[50].port(:y) << b[49].port(:y)
172
+ b[51].port(:y) << b[50].port(:y)
173
+
174
+ @a.x = 987.789
175
+ assert_equal(@a.x, b[99].y)
176
+ assert_equal(@a.x, b[0].y)
177
+ assert_equal(@a.x, old_b_50.y)
178
+ end
179
+
180
+ def make_circle n
181
+ b = (0...n).map {@world.create(B)}
182
+ n.times do |i|
183
+ b[i].port(:y) << b[(i+1)%n].port(:y)
184
+ end
185
+ b
186
+ end
187
+
188
+ def test_connect_input_circular
189
+ [1, 2, 3, 10].each do |n|
190
+ b = make_circle(n)
191
+ assert_raises(RedShift::CircularDefinitionError) do
192
+ b[0].y
193
+ end
194
+ end
195
+ end
196
+
197
+ def test_connect_input_flow
198
+ b = (0..5).map {@world.create(B)}
199
+ (0..4).each do |i|
200
+ b[i+1].port(:y) << b[i].port(:y)
201
+ end
202
+ b[0].port(:y) << @a.port(:x)
203
+
204
+ @b.port(:y) << @a.port(:x) # ust so guard doesn't find y unconn.
205
+
206
+ @a.x = 1.0
207
+ assert_equal(@a.x, b[5].y)
208
+ assert_equal(@a.x, b[0].y)
209
+
210
+ @world.evolve 10
211
+ assert_equal(@a.x, b[5].y)
212
+ assert_equal(@a.x, b[0].y)
213
+ end
214
+
215
+ def test_connect_input_multiple
216
+ @b.port(:y) << @a.port(:x)
217
+ @b.port(:yy) << @b.port(:y) # Can connect to another var in self!
218
+ @a.x = 1.0
219
+ assert_equal(@a.x*2, @b.w)
220
+ end
221
+
222
+ def test_linked_input
223
+ @a.x = 99.876
224
+
225
+ @b.other = @world.create(B)
226
+ @b.other.port(:y) << @a.port(:k)
227
+
228
+ assert_equal(@b.other.y, @a.k)
229
+ assert_equal(@b.other.y, @b.u)
230
+ end
231
+
232
+ def test_marshal
233
+ @a.x = -3.21
234
+ @b.port(:y) << @a.port(:x)
235
+ assert_equal(@a.x, @b.y)
236
+
237
+ world2 = Marshal.load(Marshal.dump(@world))
238
+ a = world2.grep(A).first
239
+ b = world2.grep(B).first
240
+ assert_equal(a.x, b.y)
241
+ end
242
+ end
@@ -0,0 +1,47 @@
1
+ require "redshift"
2
+ include RedShift
3
+
4
+ class A < Component
5
+ input :in
6
+ continuous :x => 1
7
+ link :comp
8
+
9
+ state :T
10
+
11
+ flow T do
12
+ diff " x' = in "
13
+ end
14
+
15
+ transition Enter => T do
16
+ reset :comp => nil
17
+ connect :in => proc {comp.port(:x)}
18
+ end
19
+ end
20
+
21
+ #-----#
22
+
23
+ require 'test/unit'
24
+
25
+ class TestConnect < Test::Unit::TestCase
26
+
27
+ def setup
28
+ @world = World.new
29
+ @world.time_step = 0.001
30
+ @a0 = @world.create(A)
31
+ @a1 = @world.create(A)
32
+ @a0.comp = @a1
33
+ @a1.comp = @a0
34
+ end
35
+
36
+ def teardown
37
+ @world = nil
38
+ end
39
+
40
+ def test_evolve
41
+ @world.evolve 1
42
+ [@a0, @a1].each do |a|
43
+ assert_in_delta(Math::E, a.in, 1.0e-12)
44
+ assert_equal(nil, a.comp)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,135 @@
1
+ require "redshift"
2
+ include RedShift
3
+
4
+ class A < Component
5
+ continuous :ns_x
6
+ strictly_continuous :x
7
+
8
+ constant :ns_k
9
+ strictly_constant :k => 6.78
10
+
11
+ flow do
12
+ diff " x' = 2*x "
13
+ end
14
+ end
15
+
16
+ class B < Component
17
+ strict_input :y
18
+ transition Enter => Exit do
19
+ name "t"
20
+ guard "y > 5"
21
+ end
22
+ end
23
+
24
+ class Dummy < Component
25
+ state :S, :T, :U
26
+ setup do
27
+ start S
28
+ end
29
+
30
+ flow S do
31
+ diff "time' = 1"
32
+ end
33
+
34
+ transition S => T do
35
+ guard "time > 0"
36
+ reset :time => 0 # so we do it again next timestep
37
+ end
38
+
39
+ transition T => U, U => S
40
+ end
41
+
42
+ # From test_strict_continuity.rb
43
+ class SCWorld < World
44
+ def num_checks
45
+ @num_checks ||= Hash.new do |h,comp|
46
+ h[comp] = Hash.new do |h1,trans|
47
+ h1[trans] = 0
48
+ end
49
+ end
50
+ end
51
+
52
+ def hook_eval_guard(comp, guard, enabled, trans, dest)
53
+ num_checks[comp][trans.name] += 1
54
+ end
55
+ end
56
+
57
+ #-----#
58
+
59
+ require 'test/unit'
60
+
61
+ class TestConnectStrict < Test::Unit::TestCase
62
+
63
+ def setup
64
+ @world = SCWorld.new
65
+ @world.time_step = 0.1
66
+ @a = @world.create(A) {|a| a.x = 1 }
67
+ @b = @world.create(B)
68
+ @world.create(Dummy)
69
+ end
70
+
71
+ def teardown
72
+ @world = nil
73
+ end
74
+
75
+ # can connect strict_input *only* to strict var/const
76
+ def test_not_connectable
77
+ assert_raises(StrictnessError) do
78
+ @b.port(:y) << @a.port(:ns_x)
79
+ end
80
+ assert_raises(StrictnessError) do
81
+ @b.port(:y) << @a.port(:ns_k)
82
+ end
83
+ end
84
+
85
+ # can't disconnect strict_input that has been connected
86
+ def test_disconnect
87
+ @b.port(:y) << nil # ok
88
+ @b.port(:y) << @a.port(:x)
89
+ assert_raises(StrictnessError) do
90
+ @b.port(:y) << nil
91
+ end
92
+ end
93
+
94
+ # can't connect to a different component
95
+ def test_reconnect_comp
96
+ @b.port(:y) << @a.port(:x)
97
+ @b.port(:y) << @a.port(:x) # ok
98
+ assert_raises(StrictnessError) do
99
+ @b.port(:y) << @world.create(A).port(:x)
100
+ end
101
+ end
102
+
103
+ # can't connect to a different var in same component
104
+ def test_reconnect_var
105
+ @b.port(:y) << @a.port(:x)
106
+ assert_raises(StrictnessError) do
107
+ @b.port(:y) << @a.port(:k)
108
+ end
109
+ end
110
+
111
+ # can reconnect if value is the same
112
+ def test_reconnect_same_value
113
+ a = @world.create(A) do |a|
114
+ a.x = a.k = 12.34
115
+ end
116
+ @b.port(:y) << a.port(:x)
117
+ assert_nothing_raised do
118
+ @b.port(:y) << a.port(:k)
119
+ end
120
+ end
121
+
122
+ # One check per step, despite the Dummy
123
+ def test_strict_guard
124
+ @b.port(:y) << @a.port(:x)
125
+ prev = nil
126
+ @world.evolve 2 do
127
+ if @b.state == Enter
128
+ if prev
129
+ assert_equal(prev + 1, @world.num_checks[@b]["t"])
130
+ end
131
+ prev = @world.num_checks[@b]["t"]
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redshift'
4
+
5
+ include RedShift
6
+
7
+ class ConstantTestComponent < Component
8
+ def finish test
9
+ end
10
+
11
+ constant :k
12
+ strictly_constant :ks
13
+
14
+ link :other => ConstantTestComponent
15
+
16
+ state :HasOther, :Stop
17
+
18
+ transition Enter => HasOther do
19
+ guard "other"
20
+ end
21
+
22
+ flow HasOther do
23
+ diff "x' = other.k + k + other.ks + ks"
24
+ diff "t' = 1"
25
+ end
26
+
27
+ transition HasOther => Stop do
28
+ guard "t >= 1"
29
+ action do
30
+ @y = other.k + k + other.ks + ks
31
+ end
32
+ end
33
+
34
+ def assert_consistent test
35
+ if t >= 1
36
+ test.assert_in_delta(44, x, 1E-10)
37
+ test.assert_equal(44, @y)
38
+ end
39
+ end
40
+ end
41
+
42
+ #-----#
43
+
44
+ require 'test/unit'
45
+
46
+ class TestConstant < Test::Unit::TestCase
47
+
48
+ def setup
49
+ @world = World.new
50
+ end
51
+
52
+ def teardown
53
+ @world = nil
54
+ end
55
+
56
+ def test_constant
57
+ comp1 = @world.create(ConstantTestComponent) do |c1|
58
+ c1.k = 1.0
59
+ c1.ks = 10.0
60
+ end
61
+
62
+ comp2 = @world.create(ConstantTestComponent) do |c2|
63
+ c2.k = 3.0
64
+ c2.ks = 30.0
65
+ end
66
+
67
+ comp1.other = comp2
68
+ testers = [comp1, comp2]
69
+
70
+ @world.run 20
71
+ comp1.assert_consistent self
72
+ end
73
+ end
74
+