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