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,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mathn' # Use rationals for 1/2 etc.
4
+
5
+ require 'test/unit'
6
+
7
+ require 'redshift'
8
+
9
+ include RedShift
10
+
11
+ class Timer < Component
12
+ attr_accessor :x
13
+ flow { diff " x' = 1 " }
14
+ end
15
+
16
+ class TestNumerics < Test::Unit::TestCase
17
+
18
+ def setup
19
+ @world = World.new
20
+ @world.time_step = 0.1
21
+ end
22
+
23
+ def teardown
24
+ @world = nil
25
+ end
26
+
27
+ def test_rational
28
+ c = @world.create(Timer) { |timer| timer.x = 1/2}
29
+ @world.run 100
30
+ assert_in_delta(10.5, c.x, 0.000001)
31
+ end
32
+ end
33
+
34
+ ## should test NaN, Inf, precision, etc.
@@ -0,0 +1,90 @@
1
+ require 'redshift'
2
+ require 'test/unit'
3
+
4
+ class TestQueue < Test::Unit::TestCase
5
+ class Receiver < RedShift::Component
6
+ queue :q
7
+ transition Enter => Exit do
8
+ wait :q
9
+ end
10
+ end
11
+
12
+ class Sender < RedShift::Component
13
+ link :receiver => RedShift::Component
14
+ flow {diff "t'=1"}
15
+ transition Enter => Exit do
16
+ guard "t>1"
17
+ action do
18
+ receiver.q << "hello"
19
+ end
20
+ end
21
+ end
22
+
23
+ def setup
24
+ @world = RedShift::World.new
25
+ @s = @world.create(Sender)
26
+ @r = @world.create(Receiver)
27
+ @s.receiver = @r
28
+ end
29
+
30
+ def test_msg_received
31
+ @world.evolve 0.9
32
+ assert_equal(RedShift::Component::Enter, @r.state)
33
+ assert(@world.queue_sleep[@r])
34
+ @world.evolve 0.2
35
+ assert_equal(RedShift::Component::Exit, @r.state)
36
+ assert_equal("hello", @r.q.pop)
37
+ end
38
+ end
39
+
40
+ class TestQueueAndStrict < Test::Unit::TestCase
41
+ class Receiver < RedShift::Component
42
+ queue :q
43
+ strictly_continuous :x
44
+ transition Enter => Exit do
45
+ guard "x>0"
46
+ end
47
+ transition Enter => Exit do
48
+ wait :q
49
+ end
50
+ end
51
+
52
+ class Sender < RedShift::Component
53
+ link :receiver => RedShift::Component
54
+ flow {diff "t'=1"}
55
+ state :S1
56
+ transition Enter => S1 do
57
+ guard "t>1"
58
+ # this transition gives receiver a chance to go into strict sleep,
59
+ # if that bug exists in redshift
60
+ end
61
+ transition S1 => Exit do
62
+ action do
63
+ receiver.q << "hello"
64
+ end
65
+ end
66
+ end
67
+
68
+ def setup
69
+ @world = RedShift::World.new
70
+ @s = @world.create(Sender)
71
+ @r = @world.create(Receiver)
72
+ @s.receiver = @r
73
+ end
74
+
75
+ def test_msg_received
76
+ @world.evolve 0.9
77
+ assert_equal(RedShift::Component::Enter, @r.state)
78
+ while @r.state == RedShift::Component::Enter do
79
+ # Can't be in queue sleep because of the x>0 guard.
80
+ assert(!@world.queue_sleep[@r])
81
+ @world.run 1
82
+ end
83
+
84
+ # in 1 step, @r should *both* receive the message and exit,
85
+ # which shows that it did not go into strict sleep after the first
86
+ # pass thru discrete update
87
+ assert_equal(RedShift::Component::Exit, @r.state)
88
+ assert_equal("hello", @r.q.pop)
89
+ end
90
+ end
@@ -0,0 +1,115 @@
1
+ require 'redshift/queue'
2
+ require 'test/unit'
3
+
4
+ # Test queue class outside of simulation using mocked World and
5
+ # Component classes.
6
+ class TestQueueAlone < Test::Unit::TestCase
7
+ class World
8
+ attr_accessor :step_count, :discrete_step
9
+ end
10
+ class Component
11
+ attr_accessor :world, :awake
12
+ def inc_queue_ready_count
13
+ @awake = true
14
+ end
15
+ def dec_queue_ready_count
16
+ end
17
+ end
18
+
19
+ def setup
20
+ @w = World.new
21
+ @w.step_count = 0
22
+ @w.discrete_step = 0
23
+ @c = Component.new
24
+ @c.world = @w
25
+ @q = RedShift::Queue.new @c
26
+ end
27
+
28
+ def test_fifo
29
+ 3.times do |i|
30
+ @q.push i
31
+ @w.discrete_step += 1
32
+ end
33
+
34
+ a = []
35
+ 3.times do
36
+ a << @q.pop
37
+ end
38
+
39
+ assert_equal([0,1,2], a)
40
+ end
41
+
42
+ def test_unpop
43
+ @q.push 1
44
+ x = @q.pop
45
+ @q.unpop x
46
+ assert_equal(x, @q.pop)
47
+ end
48
+
49
+ def test_simultaneous_entries
50
+ @w.step_count = 123
51
+ @w.discrete_step = 42
52
+ a = [1,2,3]
53
+ a.each do |x|
54
+ @q.push x
55
+ end
56
+
57
+ head = @q.pop
58
+ assert_equal(a, head)
59
+ @q.unpop head
60
+
61
+ @w.discrete_step += 1
62
+ @q.push "some stuff"
63
+ assert_equal(a, @q.pop)
64
+ end
65
+
66
+ def test_unpop_partial
67
+ @w.step_count = 123
68
+ @w.discrete_step = 42
69
+ a = [1,2,3]
70
+ a.each do |x|
71
+ @q.push x
72
+ end
73
+
74
+ head = @q.pop
75
+ head.shift
76
+ @q.unpop head
77
+
78
+ head = @q.pop
79
+ assert_equal([2,3], head)
80
+ assert_equal(RedShift::SimultaneousQueueEntries, head.class)
81
+ head.shift
82
+ @q.unpop head
83
+
84
+ head = @q.pop
85
+ assert_equal(3, head)
86
+ end
87
+
88
+ def test_wake
89
+ @c.awake = false
90
+ @q.push 1
91
+ assert_equal(true, @c.awake)
92
+ end
93
+
94
+ def test_match_empty_queue
95
+ assert_equal(false, @q.head_matches(Object))
96
+ end
97
+
98
+ def test_match_one_entry
99
+ @q.push("foo")
100
+ assert(@q.head_matches( ))
101
+ assert(@q.head_matches( /o/ ))
102
+ assert(@q.head_matches( String, /o/, proc {|x| x.kind_of?(String)} ))
103
+
104
+ assert_equal(false, @q.head_matches( /z/ ))
105
+ assert_equal(false, @q.head_matches( Symbol ))
106
+ assert_equal(false, @q.head_matches( proc {false} ))
107
+ end
108
+
109
+ def test_match_simultaneous_entries
110
+ @q.push "foo"
111
+ @q.push "bar"
112
+ assert(@q.head_matches( /foo/ ))
113
+ assert(@q.head_matches( /bar/ ))
114
+ end
115
+ end
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redshift'
4
+
5
+ include RedShift
6
+
7
+ # Tests resets in transitions.
8
+
9
+ class A < Component
10
+ constant :k1, :k2
11
+
12
+ continuous :x
13
+ continuous :y
14
+
15
+ link :other => A
16
+
17
+ state :S1, :S2
18
+
19
+ transition Enter => S1 do
20
+ reset :y => 1 # literal value (float or int)
21
+ end
22
+
23
+ transition S1 => S2 do
24
+ reset :x => "other.x", # expr value
25
+ :y => proc {10-y}, # proc value
26
+ :k1 => "y",
27
+ :k2 => proc {42}
28
+ end
29
+
30
+ transition S2 => Exit
31
+ end
32
+
33
+ class B < Component
34
+ state :S1, :S2
35
+
36
+ start S1
37
+
38
+ flow S1 do
39
+ alg " x = 1 "
40
+ end
41
+ flow S2 do
42
+ alg " x = 2 "
43
+ end
44
+
45
+ transition S1 => S2 do
46
+ reset :x => 3
47
+ end
48
+ end
49
+
50
+ class C < Component
51
+ constant :k, :kk
52
+ state :S
53
+ transition Enter => S do
54
+ reset :k => "kk"
55
+ end
56
+ end
57
+
58
+ class ResetVarToNonFloat < Component
59
+ continuous :var
60
+ state :S
61
+ transition Enter => S do
62
+ reset :var => proc {nil}
63
+ end
64
+ end
65
+
66
+ class ResetLink < Component
67
+ link :lnk => C
68
+ state :S
69
+ transition Enter => S do
70
+ reset :lnk => proc {create(C) {|c| c.kk = 1.337}}
71
+ end
72
+ end
73
+
74
+ class ResetLinkToNil < Component
75
+ link :lnk => C
76
+ state :S
77
+ transition Enter => S do
78
+ reset :lnk => proc {nil}
79
+ end
80
+ end
81
+
82
+ class ResetLinkToLiteralNil < Component
83
+ link :lnk => C
84
+ state :S
85
+ transition Enter => S do
86
+ reset :lnk => nil
87
+ end
88
+ end
89
+
90
+ class ResetLinkToWrongType < Component
91
+ link :lnk => C
92
+ state :S
93
+ transition Enter => S do
94
+ reset :lnk => proc {create(A)}
95
+ end
96
+ end
97
+
98
+ class Emitter < Component
99
+ transition Enter => Exit do
100
+ event :e => 42.0
101
+ end
102
+ end
103
+
104
+ class Receiver < Component
105
+ link :c => Emitter
106
+ constant :result
107
+ transition Enter => Exit do
108
+ sync :c => :e
109
+ event :e => 0.42
110
+ reset :result => "e + c.e"
111
+ end
112
+ end
113
+
114
+ require 'test/unit'
115
+
116
+ class TestReset < Test::Unit::TestCase
117
+
118
+ def setup
119
+ @world = World.new
120
+ @world.time_step = 0.1
121
+ end
122
+
123
+ def teardown
124
+ @world = nil
125
+ end
126
+
127
+ def test_reset
128
+ a1 = @world.create(A)
129
+ a2 = @world.create(A)
130
+
131
+ a1.other = a2
132
+ a2.other = a1
133
+
134
+ a1.x = v1 = 5
135
+ a2.x = v2 = 1.23
136
+
137
+ @world.run 1
138
+
139
+ assert_equal(v2, a1.x)
140
+ assert_equal(v1, a2.x)
141
+
142
+ assert_equal(9, a1.y)
143
+ assert_equal(9, a2.y)
144
+
145
+ assert_equal(1, a1.k1)
146
+ assert_equal(42, a1.k2)
147
+ end
148
+
149
+ def test_reset_algebraic_flow_error
150
+ b = @world.create(B)
151
+
152
+ assert_equal(B::S1, b.state)
153
+ assert_equal(1, b.x)
154
+
155
+ @world.run 1
156
+
157
+ assert_equal(B::S2, b.state)
158
+ assert_equal(2, b.x)
159
+ end
160
+
161
+ # This is to test the expansion of the reset value cache.
162
+ def test_many_constant_resets
163
+ ## need to get the limit as a const
164
+ n = World::CV_CACHE_SIZE + 10
165
+ cs = (0..n).map {|i| @world.create(C) {|c| c.kk = i}}
166
+ @world.run 1
167
+ cs.each do |c|
168
+ assert_equal(c.kk, c.k)
169
+ end
170
+ end
171
+
172
+ def test_reset_var_to_wrong_type
173
+ rl = @world.create(ResetVarToNonFloat)
174
+ assert_raises(VarTypeError) {@world.run 1}
175
+ end
176
+
177
+ def test_reset_link
178
+ rl = @world.create(ResetLink)
179
+ assert_equal(nil, rl.lnk)
180
+ @world.run 1
181
+ assert_equal(C, rl.lnk.class)
182
+ assert_equal(1.337, rl.lnk.k)
183
+ end
184
+
185
+ def test_reset_link_to_nil
186
+ rl = @world.create(ResetLinkToNil)
187
+ assert_equal(nil, rl.lnk)
188
+ @world.run 1
189
+ assert_equal(nil, rl.lnk)
190
+ end
191
+
192
+ def test_reset_link_to_literal_nil
193
+ rl = @world.create(ResetLinkToLiteralNil)
194
+ assert_equal(nil, rl.lnk)
195
+ @world.run 1
196
+ assert_equal(nil, rl.lnk)
197
+ end
198
+
199
+ def test_reset_link_to_wrong_type
200
+ rl = @world.create(ResetLinkToWrongType)
201
+ assert_raises(LinkTypeError) {@world.run 1}
202
+ end
203
+
204
+ def test_reset_using_event_val
205
+ r = @world.create(Receiver) {|r| r.c = r.create(Emitter)}
206
+ @world.run 1
207
+ assert_equal(42.42, r.result)
208
+ end
209
+ end