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,34 @@
1
+ require 'pp'
2
+
3
+ #
4
+ # Note: This is not a complete program specification, since Procs and methods
5
+ # cannot be dumped. It is useful for inspecting the vars, flows, and also
6
+ # transitions, to the extent that these are defined without Procs.
7
+ #
8
+
9
+ class World
10
+ def World.new(*args)
11
+ exit ## could just call the code below and then exit...
12
+ end
13
+ end
14
+
15
+ END {
16
+ ## this duplicates some code from Library
17
+ cc = []
18
+ ObjectSpace.each_object(Class) do |cl|
19
+ cc << cl if cl < Component # Component is abstract
20
+ end
21
+ cc = cc.sort_by {|c| c.ancestors.reverse!.map!{|d|d.to_s}}
22
+
23
+ cc.each do |c|
24
+ puts "=" * 60
25
+ puts "=" * 20 + "class #{c.name}"
26
+ c.instance_eval do
27
+ instance_variables.each do |var|
28
+ val = eval(var)
29
+ puts "#{var}:"
30
+ pp val
31
+ end
32
+ end
33
+ end
34
+ }
@@ -0,0 +1,300 @@
1
+ require 'pstore'
2
+
3
+ module RedShift
4
+
5
+ class ZenoError < RuntimeError; end
6
+
7
+ # Set zeno_level to this to turn off zeno checking.
8
+ ZENO_UNLIMITED = -1
9
+
10
+ class World
11
+ include Enumerable
12
+
13
+ {
14
+ :Debugger => "debugger",
15
+ :ZenoDebugger => "zeno-debugger"
16
+ }.each {|m,f| autoload(m, "redshift/mixins/#{f}")}
17
+
18
+ class ComponentList
19
+ include Enumerable
20
+
21
+ attr_reader :summands
22
+
23
+ def initialize(*summands)
24
+ @summands = summands
25
+ end
26
+
27
+ def each(&block)
28
+ summands.each { |enum| enum.each(&block) }
29
+ self
30
+ end
31
+
32
+ def size
33
+ summands.inject(0) { |sum,enum| sum + enum.size }
34
+ end
35
+
36
+ def inspect
37
+ to_a.inspect # looks better in irb, but slow
38
+ end
39
+
40
+ def [](idx)
41
+ warn "World#[] is deprecated"
42
+ to_a[idx] ## very inefficient
43
+ end
44
+
45
+ def clear
46
+ summands.each {|list| list.clear}
47
+ end
48
+ end
49
+
50
+ @subclasses = []
51
+
52
+ class << self
53
+ # World is not included in subclasses. This returns nil when called on subs.
54
+ attr_reader :subclasses
55
+
56
+ def inherited(sub)
57
+ World.subclasses << sub
58
+ end
59
+ end
60
+
61
+ def self.new(*args, &block)
62
+ RedShift.require_target # redefines World.new
63
+ new(*args, &block) # which is what this line calls
64
+ end
65
+
66
+ attr_reader :components
67
+
68
+ def default_options
69
+ {
70
+ :name => "#{self.class}_#{@@count}",
71
+ :time_unit => "second",
72
+ :time_step => 0.1,
73
+ :zeno_limit => 100,
74
+ :clock_start => 0.0,
75
+ :clock_finish => Infinity,
76
+ }
77
+ end
78
+
79
+ @@count = 0
80
+
81
+ attr_accessor :name, :time_unit
82
+
83
+ def started?; @started; end
84
+ def running?; @running; end
85
+
86
+ # Can override the options using assignments in the block.
87
+ # Note that clock_start should not be assigned after the block.
88
+ def initialize # :yields: world
89
+ self.curr_A = []; self.curr_P = []; self.curr_CR = []
90
+ self.curr_S = []; self.next_S = []; self.curr_T = []
91
+ self.active_E = []; self.prev_active_E = []
92
+ self.awake = []; self.prev_awake = []
93
+ self.strict_sleep = []; self.inert = []
94
+ self.diff_list = []; self.queue_sleep = {}
95
+ @components = ComponentList.new \
96
+ awake, prev_awake, curr_T, strict_sleep, inert # _not_ diff_list
97
+
98
+ options = default_options
99
+
100
+ @name = options[:name]
101
+ @time_unit = options[:time_unit]
102
+ self.time_step = options[:time_step]
103
+ self.zeno_limit = options[:zeno_limit]
104
+ self.clock_start = options[:clock_start]
105
+ self.clock_finish = options[:clock_finish]
106
+
107
+ self.step_count = 0
108
+
109
+ @@count += 1
110
+
111
+ do_defaults
112
+ yield self if block_given?
113
+
114
+ self.base_step_count = 0
115
+ self.base_clock = clock_start
116
+ end
117
+
118
+ def do_defaults
119
+ self.class.do_defaults self
120
+ end
121
+ private :do_defaults
122
+
123
+ def self.do_defaults instance
124
+ superclass.do_defaults instance if superclass.respond_to? :do_defaults
125
+ if @defaults_procs
126
+ @defaults_procs.each do |pr|
127
+ instance.instance_eval(&pr)
128
+ end
129
+ end
130
+ end
131
+
132
+ def do_setup
133
+ self.class.do_setup self
134
+ if @setup_procs
135
+ @setup_procs.each do |pr|
136
+ instance_eval(&pr)
137
+ end
138
+ @setup_procs = nil # so we can serialize
139
+ end
140
+ end
141
+ private :do_setup
142
+
143
+ def self.do_setup instance
144
+ superclass.do_setup instance if superclass.respond_to? :do_setup
145
+ if @setup_procs
146
+ @setup_procs.each do |pr|
147
+ instance.instance_eval(&pr)
148
+ end
149
+ end
150
+ end
151
+
152
+ def create(component_class)
153
+ component =
154
+ if block_given?
155
+ component_class.new(self) {|c| yield c}
156
+ else
157
+ component_class.new(self)
158
+ end
159
+
160
+ unless component.is_a? Component # Component is abstract
161
+ raise TypeError, "#{component.class} is not a Component class"
162
+ end
163
+
164
+ awake << component if component.world == self
165
+ component
166
+ end
167
+
168
+ ## is this a good idea? tests? #add ?
169
+ def remove c
170
+ if components.summands.any? {|list| list.delete(c)}
171
+ raise unless c.world == self
172
+ c.__set__world(nil)
173
+ else
174
+ raise "Tried to remove #{c} from #{self}, but its world is #{c.world}."
175
+ end
176
+ end
177
+
178
+ # All evolution methods untimately call step, which can be overridden.
179
+ # After each step, yields to block. It is the block's responsibility to
180
+ # step_discrete at this point after changing any vars.
181
+ def step(steps = 1)
182
+ @running = true
183
+
184
+ unless @started
185
+ do_setup
186
+ @started = true
187
+ end
188
+
189
+ step_discrete
190
+ steps.to_i.times do
191
+ break if clock > clock_finish
192
+ self.step_count += 1
193
+ step_continuous
194
+ step_discrete
195
+ @running = false
196
+ yield self if block_given?
197
+ @running = true
198
+ end
199
+
200
+ self
201
+
202
+ ensure
203
+ @running = false
204
+ ## how to continue stepping after an exception?
205
+ end
206
+
207
+ def run(*args, &block)
208
+ ## warn "World#run is deprecated -- use #step or #evolve"
209
+ step(*args, &block)
210
+ end
211
+
212
+ def evolve(time = 1.0, &block)
213
+ run((time.to_f/time_step).round, &block)
214
+ end
215
+
216
+ # Default implementation is to raise RedShift::ZenoError.
217
+ def step_zeno
218
+ raise RedShift::ZenoError, "Exceeded zeno limit of #{zeno_limit}."
219
+ end
220
+
221
+ ## is this a good idea? tests?
222
+ def garbage_collect
223
+ self.components.clear
224
+ GC.start
225
+ ObjectSpace.each_object(Component) do |c|
226
+ components << c if c.world == self
227
+ end
228
+ end
229
+
230
+ def each(&b)
231
+ @components.each(&b)
232
+ end
233
+
234
+ def size
235
+ @components.size
236
+ end
237
+
238
+ def include? component
239
+ component.world == self
240
+ end
241
+ alias member? include?
242
+
243
+ def inspect
244
+ if @started
245
+ digits = -Math.log10(time_step).floor
246
+ digits = 0 if digits < 0
247
+
248
+ data = []
249
+ data << "%d step%s" % [step_count, ("s" if step_count != 1)]
250
+ data << "%.#{digits}f #{@time_unit}%s" % [clock, ("s" if clock != 1)]
251
+ data << "%d component%s" % [size, ("s" if size != 1)]
252
+ data << "discrete step = #{discrete_step}" ## only if in step_discrete?
253
+ else
254
+ data = ["not started. Do 'run 0' to setup, or 'run n' to run."]
255
+ end
256
+
257
+ str = [name, data.join("; ")].join(": ")
258
+ "<#{str}>"
259
+ end
260
+
261
+ def save filename = @name
262
+ raise "Can't save world during its run method." if @running
263
+ File.delete(filename) rescue SystemCallError
264
+ store = PStore.new filename
265
+ store.transaction do
266
+ store['world'] = self
267
+ yield store if block_given?
268
+ end
269
+ end
270
+
271
+ def World.open filename
272
+ RedShift.require_target
273
+ commit
274
+
275
+ world = nil
276
+ store = PStore.new filename
277
+ store.transaction do
278
+ if store.root? 'world'
279
+ world = store['world']
280
+ yield store if block_given?
281
+ end
282
+ end
283
+ world
284
+ end
285
+
286
+ # This is for when Component#world is nonpersistent
287
+ # def __restore__world__refs
288
+ # ## need this list because @components is not restored yet
289
+ # [awake, prev_awake, curr_T, strict_sleep, inert].each do |list|
290
+ # list.each do |c|
291
+ # c.send :__set__world, self
292
+ # end
293
+ # end
294
+ # ## could be in C
295
+ # end
296
+ # private :__restore__world__refs
297
+
298
+ end # class World
299
+
300
+ end # module RedShift
data/rakefile ADDED
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bones'
3
+ rescue LoadError
4
+ abort '### please install the bones gem ###'
5
+ end
6
+
7
+ ensure_in_path 'lib'
8
+ require 'redshift'
9
+
10
+ Bones {
11
+ name 'redshift'
12
+ authors 'Joel VanderWerf'
13
+ email 'vjoel@users.sourceforge.net'
14
+ url 'http://rubyforge.org/projects/redshift'
15
+ rubyforge.name 'redshift'
16
+ version RedShift::VERSION
17
+ readme_file 'README'
18
+
19
+ summary 'Simulation of hybrid automata'
20
+ description <<END
21
+ A framework for simulation of networks of hybrid automata, similar to SHIFT and Lambda-SHIFT. Includes ruby-based DSL for defining simulation components, and ruby/C code generation and runtime.
22
+ END
23
+
24
+ depend_on 'cgen'
25
+
26
+ history_file 'RELEASE-NOTES'
27
+ changes File.read(history_file)[/^\w.*?(?=^\w)/m]
28
+ (rdoc.dir File.readlink(rdoc.dir)) rescue nil
29
+
30
+ spec.opts << '--color'
31
+ test.files = Dir["test/test-*.rb"]
32
+ }
33
+
34
+ task :release => ["rubyforge:release", "rubyforge:doc_release"]
35
+
36
+ # EOF
37
+
data/test/test.rb ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if RUBY_VERSION == "1.6.6"
4
+ puts "DEBUG mode is turned off in Ruby 1.6.6 due to bug."
5
+ $DEBUG = false
6
+ else
7
+ $DEBUG = true
8
+ end
9
+
10
+ if RUBY_VERSION == "1.8.0"
11
+ class Module
12
+ alias instance_methods_with_warning instance_methods
13
+ def instance_methods(include_super=true)
14
+ instance_methods_with_warning(include_super)
15
+ end
16
+ end
17
+ end
18
+
19
+ $REDSHIFT_DEBUG=3 ## what should this be?
20
+
21
+ ### have to fix the CLIB_NAME problem before can do this
22
+ ### require 'redshift' ## all the tests will need this anyway
23
+
24
+ pat = ARGV.join("|")
25
+ tests = Dir["test_*.rb"].grep(/#{pat}/)
26
+ tests.sort!
27
+
28
+ #trap("CLD") do
29
+ # # trapping "INT" doesn't work because child gets the signal
30
+ # exit!
31
+ #end
32
+
33
+ require 'rbconfig'
34
+ ruby = Config::CONFIG["RUBY_INSTALL_NAME"]
35
+
36
+ failed = tests.reject do |file|
37
+ puts "_"*50 + "\nStarting #{file}...\n"
38
+ system "#{ruby} #{file}"
39
+ # pid = fork { ## should use popen3 so we can weed out successful output
40
+ # $REDSHIFT_CLIB_NAME = file
41
+ # require 'redshift'
42
+ # load file
43
+ # }
44
+ # Process.waitpid(pid)
45
+ end
46
+
47
+ puts "_"*50
48
+ if failed.empty?
49
+ puts "All tests passed."
50
+ else
51
+ puts "Some tests failed:", failed
52
+ end
@@ -0,0 +1,58 @@
1
+ require 'redshift'
2
+
3
+ include RedShift
4
+
5
+ RedShift.with_library do |library|
6
+ require "redshift/target/c/flow/buffer"
7
+ library.define_buffer
8
+ end
9
+
10
+ require 'test/unit'
11
+
12
+ class TestBuffer < Test::Unit::TestCase
13
+
14
+ class T < Component
15
+ RedShift.with_library do
16
+ shadow_attr_accessor :b => "Buffer b"
17
+ end
18
+ end
19
+
20
+ def setup
21
+ @world = World.new
22
+ @t = @world.create(T)
23
+ end
24
+
25
+ def teardown
26
+ @world = nil
27
+ end
28
+
29
+ def test_accessor
30
+ a = [1.0, 2.0, 3.0, 4.0]
31
+ @t.b = a
32
+ assert_equal(a, @t.b)
33
+ end
34
+
35
+ def test_empty
36
+ assert_equal([], @t.b)
37
+ end
38
+
39
+ def test_marshal
40
+ t2 = Marshal.load(Marshal.dump(@t))
41
+ assert_equal(@t.b, t2.b)
42
+ end
43
+
44
+ def make_garbage
45
+ 5.times do
46
+ @world = World.new
47
+ @world.create(T)
48
+ end
49
+ end
50
+
51
+ def test_gc
52
+ make_garbage
53
+ n1 = ObjectSpace.each_object(T) {}
54
+ GC.start
55
+ n2 = ObjectSpace.each_object(T) {}
56
+ assert(n2 < n1)
57
+ end
58
+ end