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