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
data/TODO ADDED
@@ -0,0 +1,431 @@
1
+ Publishing RedShift
2
+ ===================
3
+
4
+ core for 1.3 release
5
+
6
+ clean up world (save/load etc)
7
+ tracer
8
+ event value conditions in sync clause?
9
+ sync :client => check(:accept){|val| val==self}
10
+ # from sync-queue.rb
11
+
12
+ doc, tutorial, web site
13
+
14
+ clean up tests, examples
15
+
16
+ user tools
17
+ zeno and other debuggers
18
+ shell
19
+ visualization interfaces: tkar, gnuplot, opengl
20
+
21
+ benchmarks
22
+ - compare with stateflow and simulink examples
23
+ - try to scale these examples up
24
+ - compare with Ptolemy -- ask devs for good benchmarks
25
+
26
+ packaging and project mgmt
27
+ - windows w/ several compilers
28
+
29
+ notify
30
+ - shift-dev folks, hs researchers (e.g., Joao Hispanha, Ed Lee)
31
+ - contacts who have expressed interest in redshift or shift
32
+ - others:
33
+ http://www.dis.anl.gov/exp/cas/index.html
34
+ http://www.artcompsci.org
35
+ Sylvain Joyeux (esp. re: distributed simulation)
36
+ Martin Fowler (see http://martinfowler.com/dslwip/)
37
+
38
+ publicize
39
+ - http://path.berkeley.edu/shift/
40
+ (this is still the first google hit for "hybrid system simulation")
41
+ - ruby-talk, sciruby
42
+ - comp.simulation, comp.soft-sys.(matlab|ptolemy), scs.org
43
+ - paper?
44
+
45
+ funding
46
+ - nsf or sbir
47
+ - need to emphasize research goals:
48
+ - distributed hybrid simulation
49
+ - further optimizations like strict
50
+ - approach potential users in industry
51
+ - GM, with wrapping for CarSim dll
52
+
53
+ long-term goals
54
+ - multiple clocks and threshold crossing detection, as in:
55
+ http://repository.upenn.edu/ese_papers/123/
56
+ - vector-valued signals
57
+ - need proper C parsing first
58
+ - user-friendly interface and related tools
59
+ - distributed simulation (HLA. CERTI?)
60
+ - library of integrators/flows and components
61
+ - jruby/jvm port (and use duby for actions etc)
62
+ - import models from simulink, Ptolemy, HSIF, etc.
63
+ - interface at run time with simulink etc.
64
+ - redshift as simulink block
65
+ - rt code generation?
66
+ - HLA support for interoperability
67
+
68
+ backronym: Ruby-based Efficient Deterministic SHIFT
69
+
70
+
71
+
72
+
73
+ To do
74
+ =====
75
+
76
+ Project
77
+
78
+ Subversion, gems, etc.
79
+
80
+ Docs and tutorial
81
+
82
+ Bugs
83
+
84
+ Make sure the arrays used internally are not shared:
85
+ call rb_ary_modify() before setting len or etc.
86
+
87
+ what happens if an exception (or throw or break) happens inside
88
+ of a block during discrete_update? (e.g. an action, reset, or
89
+ guard block)
90
+
91
+ Syntax
92
+
93
+ better sync syntax to avoid the :l=>:e, :l=>:f prob
94
+ sync {l.e, l.f} ?
95
+
96
+ should define, for each link, a TransitionParser method which returns
97
+ a dummy link object that responds to #event and returns
98
+ a dummy event that responds to #==(value) so that you can write
99
+
100
+ guard link_var.some_event == 123
101
+
102
+ instead of
103
+
104
+ [:link_var, :some_event, 123]
105
+
106
+ should be possible to allow:
107
+
108
+ reset x => ... instead of reset :x => ...
109
+
110
+ replace strictly_* with strict_* and alias back for compat
111
+
112
+ express flows, guards, etc, in ruby syntax and use something to parse:
113
+
114
+ nodedump/nodewrap
115
+
116
+ ripper
117
+
118
+ "expansion.rb"
119
+
120
+ vars are class methods returning Var obejcts
121
+
122
+ resets and even assignment to cont-vars can use '<<'
123
+
124
+ equations can use '=='
125
+
126
+ reset syntax:
127
+
128
+ reset do
129
+ x 3
130
+ y "x+2"
131
+ z { (x-y).abs }
132
+
133
+ check for symbol conflicts
134
+ user attributes may conflict with Component's attrs
135
+ ditto for flows and other methods defined in subclasses
136
+ can we 'hook' method def and attr def to check for conflict?
137
+ or just use a consistent naming scheme to keep internals separate?
138
+
139
+ flow /Foo.*/ ...
140
+ matches on name of states
141
+
142
+ Semantics
143
+
144
+ export event _to_ comp? and sync on event alone w/o link?
145
+ export [:e, 4] => :lnk # sender
146
+ sync :e # receiver
147
+
148
+ add check for values of event after sync
149
+ (and then repeat sync loop)
150
+ "sync :l => {:e => 3}" or better syntax
151
+
152
+ option to initialize all float vars to NaN?
153
+
154
+ ideas from Verilog?
155
+
156
+ ideas from DEVS? (http://moncs.cs.mcgill.ca/people/tfeng/thesis/node12.html)
157
+
158
+ "Buffer" could be used for:
159
+
160
+ - recurrence relations/ difference equations:
161
+
162
+ recurrence " x = x[-0.1] + x[-0.2] "
163
+
164
+ - input data (possibly interpolated) from table/file/etc
165
+
166
+ - output to data (or file) faster than ruby array of double
167
+
168
+ ( record " expr " => file ? )
169
+
170
+ Use NArray of doubles for this?
171
+
172
+ Better: array of ptr to 1K blocks of float/double
173
+
174
+ Per state syntax:
175
+
176
+ some_state.record var => "expr"
177
+
178
+ var refers to array of bocks of raw data
179
+
180
+ expr is evaled after discrete update
181
+
182
+ - need a language for piping data streams:
183
+
184
+ src | x | integrate | ... | dst
185
+
186
+ register event observers:
187
+ on comp=>event do ... end
188
+
189
+ Does permissive make sense?
190
+
191
+ inheritance among states:
192
+
193
+ "state Foo has everything that Bar has, plus ...."
194
+
195
+ a transition that can happen only once per discrete step, to easily
196
+ prevent zeno pb (useful for utility transitions, such as output)
197
+
198
+ better: a "pre-strict" var that can only get reset once per step
199
+
200
+ per-state strictness?
201
+
202
+ if guard "strictvar && something" is checked and strictvar is false,
203
+ then the guard doesn't need to be checked again, regardless of "something"
204
+ similarly for: guard "strictvar"; guard "something"
205
+
206
+ "finalizers" for components -- called when component exits, world
207
+ is finalized, or app quits
208
+
209
+ more generally, code that executes when a given state is entered:
210
+
211
+ state Exit do
212
+ # do some finalization stuff here
213
+ end
214
+
215
+ Or:
216
+
217
+ entering SomeState do...end
218
+ exiting SomeState do...end
219
+
220
+ Maybe this is better handled by adding another state (PreSomeState)
221
+
222
+ abstract classes (no code generated)
223
+
224
+ input events (in place of interrupts?)
225
+
226
+ as opposed to normal events, which are output (pull vs. push)
227
+
228
+ but does this mean arriving events are queued?
229
+
230
+ this would be useful for timers so that client component doesn't
231
+ have to manage a ref to the timer
232
+
233
+ wait/sleep
234
+
235
+ in a transition, saying "sleep n" says that the component will not
236
+ check guards for the rest of that discrete update and for n time units.
237
+
238
+ exception handler clauses in transitions (or use interrupts?)
239
+ on LockFailed { |var, value| ... }
240
+
241
+ state stack:
242
+ a transition (or interrupt) can push the current state or pop back
243
+ to a previously saved state (like Kader's idea)
244
+ syntax:
245
+ transition ... do
246
+ push [or pop, in which case the dest. state is ignored]
247
+ end
248
+
249
+ interrupts
250
+ a way of enabling a transition without evaluating guards
251
+ -faster
252
+ can do sender-receiver, rather than broadcast
253
+ can register with global interrupt manager
254
+ notify after T seconds
255
+ notify when global event happens (like what?)
256
+ receive in any state, switch to new state optional (push ok)
257
+ synchronous in the sense that no other components act in between
258
+ the send and receive, and the receiver action happens before the
259
+ sender action finishes (?)
260
+ but not parallel assignment
261
+ based on methods
262
+ in sender's action clause: 'x.foo args'
263
+ in receiver:
264
+ interrupt :foo => NewState do
265
+ action { |args| ...}
266
+ event ...
267
+ end
268
+
269
+ signals
270
+ maybe better than interrupts, more general
271
+
272
+ transition ... do
273
+ signal value => receiver_collection, ...
274
+ end
275
+
276
+ on value do ... end
277
+
278
+ is this better than a simple method call?
279
+ yes: can implement queue
280
+
281
+ discrete evolution
282
+ more flexibility:
283
+ start actions as well as finish actions
284
+ (before/after)
285
+ enter and exit blocks for each state
286
+ start_when and finish_when to implement sync
287
+ transitions like in statechart
288
+ parametric transitions?
289
+ attach :all, ...
290
+ syncronization
291
+ explicit?
292
+
293
+ exceptions
294
+ catch them if they arise in action
295
+ pass them on to handler where?
296
+
297
+ might be better not to raise or rb_raise, but to call redshift_error on the
298
+ world class, which the class could override as needed
299
+
300
+ Component#teardown called after exit
301
+ maybe #setup should only be called at last moment before running,
302
+ so that setup clauses can be added later
303
+
304
+ Implementation
305
+
306
+ use static functions where possible
307
+
308
+ decouple expr code from particular states/transitions so that
309
+ two state can share code
310
+ changing state name doesn't cause (much) recompile
311
+ etc.
312
+
313
+ option to dump all C code to one file (amalgam), so compiler can optimize more
314
+
315
+ improve performance of event and local storage by using native (NVector)
316
+ where possible, but keeping ruby array for ruby values
317
+
318
+ remove -g (if not debug) from CFLAGS
319
+ add -march=i686 -msse2 -mfpmath=sse (keep -fPIC?)
320
+ or whatever current hw is (how to determine that?)
321
+
322
+ possible to use only 1 tmp value for rk4?
323
+
324
+ optimization: no ContState object, just a pointer in the comp. shadow struct
325
+ could point to area at end of component's shadow struct
326
+
327
+ revert to on-demand var evaluation during continuous update?
328
+
329
+ optimization: transitive closure of strict sleep, based on declaration
330
+ that prevents setters
331
+
332
+ optimization: weaken "strict" so that resets can apply at end of
333
+ discrete update, but still get all the optimizations (see bench/discrete.rb)
334
+
335
+ - a new kind of flow that applies an "impulse" to a strict var at the
336
+ beginning of the next cont step, or
337
+
338
+ - a declaration that a var becomes strict for the rest of the discrete
339
+ step
340
+
341
+ Allow c-coded actions:
342
+
343
+ transition do
344
+ action " func(self, x*2, lnk.y) "
345
+ end
346
+
347
+ cdef <<END
348
+ func(SelfShadowClass *self, double arg1, double arg2) {
349
+ ...
350
+ }
351
+ END
352
+
353
+ Debug mode that uses hooks to add extra checking:
354
+
355
+ - rollover check for d_tick, step_count
356
+
357
+ - check_strict (and make it *not* the default)
358
+
359
+ Instead of caching flow function in each cont var, maybe just have pointer
360
+ to a single per state object? This can also have the outgoing transitions,
361
+ and so __update_cache can be somewhat faster.
362
+
363
+ share mark and free funcs where possible (e.g., guards)
364
+
365
+ guards should not be written in numerical order (".._0", "..._1"), but
366
+ in a more meaningful way so that changing order doesn't force recompile
367
+
368
+ unified internal repr. for phases
369
+
370
+ insert a mnemonic for quick detection of phase type in discrete update
371
+
372
+ distribute Init_clib better
373
+
374
+ break flow-gen.rb and world-gen.rb into several files each
375
+ flow-gen files can be loaded on demand as flow types are needed
376
+ most of world-gen can be a .c file used as a template
377
+
378
+ optimization
379
+ profiling
380
+ use valgrind, gprof, etc. to profile the C code
381
+ compare with shift, matlab
382
+
383
+ compile time error checking:
384
+ translate C compiler error (e.g. bad result type in expr) to ruby exception
385
+
386
+ run time error checking
387
+ more 'if $DEBUG ...' checks
388
+ catch definition of flows after commit, etc.
389
+
390
+ exception handling
391
+ syntax and math errors, esp. in flows, guards
392
+ use Exception classes
393
+
394
+ error messages
395
+
396
+ Current file/line position must be saved by many constructs, e.g. reset,
397
+ so that it can be shown later if there is an error message
398
+
399
+ use ", []" to avoid showing backtrace when it is not helpful
400
+
401
+ exceptions in C code sometimes don't give symbolic info, like var names
402
+
403
+ check against ruby 1.9
404
+
405
+ replace RARRAY(x)->len with RARRAY_LEN(x)
406
+
407
+ libtcc backend
408
+
409
+ dot backend (see file in lib dir)
410
+
411
+ optimization: split diff_list for different integrators, so comps with
412
+ only euler flows don't get iterated over as much
413
+
414
+ User interface
415
+
416
+ yaml and pp outputs
417
+
418
+ Tools
419
+
420
+ profiler mixin for World (also an executable script?)
421
+
422
+ debugger mixin for World (also an executable script?)
423
+
424
+ generalize the irb-shell.rb and TO4230 shells, and make RedShift::Shell
425
+
426
+ use this in ZenoDebugger, too
427
+
428
+ can this be a mixin for World
429
+
430
+ general vis interface using TkCanvas/tkar or opengl
431
+
@@ -0,0 +1,61 @@
1
+ require 'redshift'
2
+ require 'enumerator'
3
+
4
+ include RedShift
5
+
6
+ module AlgState
7
+ class PureAlg < Component
8
+ # An algebraic state is one that has no diff flows in its
9
+ # current state. However, algebraic flows are allowed.
10
+ #
11
+ # The diff_list optimization improves performance by about
12
+ # a factor of 5.
13
+ #
14
+ flow do
15
+ alg " x = 1 "
16
+ end
17
+ end
18
+
19
+ class NonAlg < Component
20
+ flow do
21
+ diff " t' = 1 "
22
+ end
23
+ end
24
+
25
+ def self.make_world n_alg, n_non_alg=0
26
+ w = World.new
27
+ n_alg.times {w.create(PureAlg)}
28
+ n_non_alg.times {w.create(NonAlg)}
29
+ w
30
+ end
31
+
32
+ def self.do_bench
33
+ [0].each do |n_non_alg|
34
+ [ [ 0, 1_000],
35
+ [ 10, 1_000],
36
+ [ 100, 1_000],
37
+ [ 1000, 1_000],
38
+ [ 10000, 1_000] # cache nonlinearity happens here!
39
+ ].each do
40
+ | n_alg, n_s|
41
+
42
+ w = make_world(n_alg, n_non_alg)
43
+ w.run 1 # warm up
44
+ r = bench do
45
+ w.run(n_s)
46
+ end
47
+
48
+ yield " - %10d comps X %10d steps X %10d non-alg: %8.2f" %
49
+ [n_alg, n_s, n_non_alg, r]
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ if __FILE__ == $0
56
+
57
+ require File.join(File.dirname(__FILE__), 'bench')
58
+ puts "alg-state:"
59
+ AlgState.do_bench {|l| puts l}
60
+
61
+ end