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.
- data/.gitignore +8 -0
- data/README +5 -0
- data/RELEASE-NOTES +455 -0
- data/TODO +431 -0
- data/bench/alg-state.rb +61 -0
- data/bench/bench +26 -0
- data/bench/bench.rb +10 -0
- data/bench/continuous.rb +76 -0
- data/bench/diff-bench +86 -0
- data/bench/discrete.rb +101 -0
- data/bench/euler.rb +50 -0
- data/bench/formula.rb +78 -0
- data/bench/half-strict.rb +103 -0
- data/bench/inertness.rb +116 -0
- data/bench/queue.rb +92 -0
- data/bench/run +66 -0
- data/bench/simple.rb +74 -0
- data/bench/strictness.rb +86 -0
- data/examples/ball-tkar.rb +72 -0
- data/examples/ball.rb +123 -0
- data/examples/collide.rb +70 -0
- data/examples/connect-parallel.rb +48 -0
- data/examples/connect.rb +109 -0
- data/examples/constants.rb +27 -0
- data/examples/delay.rb +80 -0
- data/examples/derivative.rb +77 -0
- data/examples/euler.rb +46 -0
- data/examples/external-lib.rb +33 -0
- data/examples/guard-debugger.rb +77 -0
- data/examples/lotka-volterra.rb +33 -0
- data/examples/persist-ball.rb +68 -0
- data/examples/pid.rb +87 -0
- data/examples/ports.rb +60 -0
- data/examples/queue.rb +56 -0
- data/examples/queue2.rb +98 -0
- data/examples/reset-with-event-val.rb +28 -0
- data/examples/scheduler.rb +104 -0
- data/examples/set-dest.rb +23 -0
- data/examples/simulink/README +1 -0
- data/examples/simulink/delay.mdl +827 -0
- data/examples/simulink/derivative.mdl +655 -0
- data/examples/step-discrete-profiler.rb +103 -0
- data/examples/subsystem.rb +109 -0
- data/examples/sync-deadlock.rb +32 -0
- data/examples/sync-queue.rb +91 -0
- data/examples/sync-retry.rb +20 -0
- data/examples/sync.rb +51 -0
- data/examples/thermostat.rb +53 -0
- data/examples/zeno.rb +53 -0
- data/lib/accessible-index.rb +47 -0
- data/lib/redshift.rb +1 -0
- data/lib/redshift/component.rb +412 -0
- data/lib/redshift/meta.rb +183 -0
- data/lib/redshift/mixins/zeno-debugger.rb +69 -0
- data/lib/redshift/port.rb +57 -0
- data/lib/redshift/queue.rb +104 -0
- data/lib/redshift/redshift.rb +111 -0
- data/lib/redshift/state.rb +31 -0
- data/lib/redshift/syntax.rb +558 -0
- data/lib/redshift/target/c.rb +37 -0
- data/lib/redshift/target/c/component-gen.rb +1303 -0
- data/lib/redshift/target/c/flow-gen.rb +325 -0
- data/lib/redshift/target/c/flow/algebraic.rb +85 -0
- data/lib/redshift/target/c/flow/buffer.rb +74 -0
- data/lib/redshift/target/c/flow/delay.rb +203 -0
- data/lib/redshift/target/c/flow/derivative.rb +101 -0
- data/lib/redshift/target/c/flow/euler.rb +67 -0
- data/lib/redshift/target/c/flow/expr.rb +113 -0
- data/lib/redshift/target/c/flow/rk4.rb +80 -0
- data/lib/redshift/target/c/library.rb +85 -0
- data/lib/redshift/target/c/world-gen.rb +1370 -0
- data/lib/redshift/target/spec.rb +34 -0
- data/lib/redshift/world.rb +300 -0
- data/rakefile +37 -0
- data/test/test.rb +52 -0
- data/test/test_buffer.rb +58 -0
- data/test/test_connect.rb +242 -0
- data/test/test_connect_parallel.rb +47 -0
- data/test/test_connect_strict.rb +135 -0
- data/test/test_constant.rb +74 -0
- data/test/test_delay.rb +145 -0
- data/test/test_derivative.rb +48 -0
- data/test/test_discrete.rb +592 -0
- data/test/test_discrete_isolated.rb +92 -0
- data/test/test_exit.rb +59 -0
- data/test/test_flow.rb +200 -0
- data/test/test_flow_link.rb +288 -0
- data/test/test_flow_sub.rb +100 -0
- data/test/test_flow_trans.rb +292 -0
- data/test/test_inherit.rb +127 -0
- data/test/test_inherit_event.rb +74 -0
- data/test/test_inherit_flow.rb +139 -0
- data/test/test_inherit_link.rb +65 -0
- data/test/test_inherit_setup.rb +56 -0
- data/test/test_inherit_state.rb +66 -0
- data/test/test_inherit_transition.rb +168 -0
- data/test/test_numerics.rb +34 -0
- data/test/test_queue.rb +90 -0
- data/test/test_queue_alone.rb +115 -0
- data/test/test_reset.rb +209 -0
- data/test/test_setup.rb +119 -0
- data/test/test_strict_continuity.rb +410 -0
- data/test/test_strict_reset_error.rb +30 -0
- data/test/test_strictness_error.rb +32 -0
- data/test/test_sync.rb +185 -0
- data/test/test_world.rb +328 -0
- metadata +204 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
# Numerical differentiation.
|
2
|
+
|
3
|
+
# Compare with simulink/derivative.mdl -- note that redshift is more accurate
|
4
|
+
# because the derivative flow operates at all integrator steps, not just at
|
5
|
+
# the simulation timesteps.
|
6
|
+
|
7
|
+
require 'redshift'
|
8
|
+
include RedShift
|
9
|
+
|
10
|
+
class C < Component
|
11
|
+
flow do
|
12
|
+
diff " t' = 1 "
|
13
|
+
|
14
|
+
alg " u = sin(t) "
|
15
|
+
alg " sdu = cos(t) " # symbolic derivative
|
16
|
+
derive " ndu = u' ",# numerical derivative (can be (<expr>)' )
|
17
|
+
:feedback => false
|
18
|
+
diff " nindu' = ndu " # numerical integral of ndu
|
19
|
+
diff " niu' = u " # numerical integral of u
|
20
|
+
derive " ndniu = niu' ",# numerical derivative of niu
|
21
|
+
:feedback => false
|
22
|
+
|
23
|
+
alg " err = sdu - ndu "
|
24
|
+
# This error is small.
|
25
|
+
|
26
|
+
alg " e_ndni = ndniu - u "
|
27
|
+
alg " e_nind = nindu - u "
|
28
|
+
# The error is very small when numerically differentiating a signal that
|
29
|
+
# has been numerically integrated (e_ndni), but the error is worse
|
30
|
+
# for the integral of a differentiated signal (e_nind).
|
31
|
+
end
|
32
|
+
|
33
|
+
# Some alternative examples:
|
34
|
+
# alg " u = pow(t, 4) - 17*pow(t,3) + 102*pow(t,2) - 1300*t "
|
35
|
+
# alg " sdu = 4*pow(t, 3) - 3*17*pow(t,2) + 2*102*t - 1300 "
|
36
|
+
#
|
37
|
+
# continuous :u => 1, :nindu => 1, :ndniu =>1
|
38
|
+
# diff " u' = 0.02*u "
|
39
|
+
# alg " sdu = 0.02*exp(0.02*u) "
|
40
|
+
end
|
41
|
+
|
42
|
+
world = World.new
|
43
|
+
c = world.create(C)
|
44
|
+
|
45
|
+
u, sdu, ndu, nindu, err, e_ndni, e_nind = [], [], [], [], [], [], []
|
46
|
+
gather = proc do
|
47
|
+
time = c.t
|
48
|
+
u << [time, c.u]
|
49
|
+
sdu << [time, c.sdu]
|
50
|
+
ndu << [time, c.ndu]
|
51
|
+
nindu << [time, c.nindu]
|
52
|
+
err << [time, c.err]
|
53
|
+
e_ndni << [time, c.e_ndni]
|
54
|
+
e_nind << [time, c.e_nind]
|
55
|
+
end
|
56
|
+
|
57
|
+
gather.call
|
58
|
+
world.evolve 10 do
|
59
|
+
gather.call
|
60
|
+
end
|
61
|
+
|
62
|
+
require 'sci/plot'
|
63
|
+
include Plot::PlotUtils
|
64
|
+
|
65
|
+
gnuplot do |plot|
|
66
|
+
plot.command %{set title "Numerical differentiation"}
|
67
|
+
plot.command %{set xlabel "time"}
|
68
|
+
plot.add u, %{title "u" with lines}
|
69
|
+
plot.add sdu, %{title "sdu" with lines}
|
70
|
+
plot.add ndu, %{title "ndu" with lines}
|
71
|
+
plot.add nindu, %{title "nindu" with lines}
|
72
|
+
plot.add err, %{title "err" with lines}
|
73
|
+
plot.add e_ndni, %{title "e_ndni" with lines}
|
74
|
+
plot.add e_nind, %{title "e_nind" with lines}
|
75
|
+
end
|
76
|
+
|
77
|
+
sleep 1 if /mswin32|mingw32/ =~ RUBY_PLATFORM
|
data/examples/euler.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'redshift'
|
2
|
+
|
3
|
+
include RedShift
|
4
|
+
|
5
|
+
class Flow_Euler < Component
|
6
|
+
flow do
|
7
|
+
euler "x' = 1"
|
8
|
+
euler "y_euler' = x" # y is a worse approx of z, due to Euler
|
9
|
+
diff " y_rk4' = x"
|
10
|
+
alg " y_true = 0.5 * pow(x,2)" # the true value
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
world = World.new
|
15
|
+
c = world.create(Flow_Euler)
|
16
|
+
|
17
|
+
|
18
|
+
x, y_euler, y_rk4, y_true, rk4_err, euler_err = [], [], [], [], [], []
|
19
|
+
gather = proc do
|
20
|
+
time = world.clock
|
21
|
+
x << [time, c.x]
|
22
|
+
y_euler << [time, c.y_euler]
|
23
|
+
y_rk4 << [time, c.y_rk4]
|
24
|
+
y_true << [time, c.y_true]
|
25
|
+
rk4_err << [time, (c.y_rk4 - c.y_true).abs]
|
26
|
+
euler_err << [time, (c.y_euler - c.y_true).abs]
|
27
|
+
end
|
28
|
+
|
29
|
+
gather.call
|
30
|
+
world.evolve 10 do
|
31
|
+
gather.call
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'sci/plot'
|
35
|
+
include Plot::PlotUtils
|
36
|
+
|
37
|
+
gnuplot do |plot|
|
38
|
+
plot.command %{set title "Euler Integration"}
|
39
|
+
plot.command %{set xlabel "time"}
|
40
|
+
plot.add x, %{title "x" with lines}
|
41
|
+
plot.add y_true, %{title "y_true" with lp}
|
42
|
+
plot.add y_rk4, %{title "y_rk4" with lp}
|
43
|
+
plot.add y_euler, %{title "y_euler" with lp}
|
44
|
+
plot.add rk4_err, %{title "rk4_err" with lp}
|
45
|
+
plot.add euler_err, %{title "euler_err" with lp}
|
46
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Example of using an external C lib with redshift. Note that
|
2
|
+
# <math.h> is included and -lm is linked by default.
|
3
|
+
|
4
|
+
require 'redshift'
|
5
|
+
|
6
|
+
RedShift.with_library do |library|
|
7
|
+
library.include_file.include "<gsl/gsl_sf_gamma.h>"
|
8
|
+
library.include_file.include "<gsl/gsl_math.h>"
|
9
|
+
library.include_file.include "<gsl/gsl_const_mksa.h>"
|
10
|
+
library.link_with "-lgsl"
|
11
|
+
library.declare_external_constant "GSL_CONST_MKSA_MASS_ELECTRON"
|
12
|
+
|
13
|
+
# If you need custom cflags, you can put them here:
|
14
|
+
# $CFLAGS = "-fPIC -O2 -march=i686 -msse2 -mfpmath=sse"
|
15
|
+
end
|
16
|
+
|
17
|
+
class C < RedShift::Component
|
18
|
+
continuous :x, :y
|
19
|
+
|
20
|
+
flow do
|
21
|
+
diff " y' = 2 + GSL_CONST_MKSA_MASS_ELECTRON "
|
22
|
+
end
|
23
|
+
|
24
|
+
transition Enter => Exit do
|
25
|
+
guard " gsl_fcmp(y, 1.0, 0.01) == 0 "
|
26
|
+
reset :x => "gsl_sf_taylorcoeff(3, 2)"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
w = RedShift::World.new
|
31
|
+
c = w.create C
|
32
|
+
w.evolve 1
|
33
|
+
p c.x, c.y
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'redshift'
|
2
|
+
|
3
|
+
include RedShift
|
4
|
+
|
5
|
+
# This example is a simple debugger for stepping through guards. It's not
|
6
|
+
# intended to be useful as a debugger, but to show how hook methods can be
|
7
|
+
# used to develop debuggers.
|
8
|
+
#
|
9
|
+
# See examples/step-discrete-hook.rb for more examples of hook methods.
|
10
|
+
#
|
11
|
+
# See mixins/debugger.rb and examples/debugger.rb for a more useful debugger.
|
12
|
+
|
13
|
+
class DebuggingWorld < World
|
14
|
+
def hook_eval_guard(comp, guard, enabled, trans, dest)
|
15
|
+
puts "%-30p %-30p %-8s %6d" %
|
16
|
+
[comp, guard, enabled ? "enabled" : nil, discrete_step]
|
17
|
+
if enabled and dest != comp.state
|
18
|
+
puts "%-30s %-30s %-s" % [nil, nil, "#{comp.state} => #{dest}"]
|
19
|
+
end
|
20
|
+
puts "press <enter> to continue"
|
21
|
+
gets
|
22
|
+
end
|
23
|
+
|
24
|
+
def hook_begin
|
25
|
+
puts "-"*60
|
26
|
+
puts "Begin discrete update in #{inspect}"
|
27
|
+
puts "press <enter> to continue, ^C at any time to stop"
|
28
|
+
puts "%-30s %-30s %-8s %6s" %
|
29
|
+
%w(component guard status step)
|
30
|
+
gets
|
31
|
+
end
|
32
|
+
|
33
|
+
def hook_end
|
34
|
+
puts "End discrete update in #{inspect}"
|
35
|
+
puts "press <enter> to continue"
|
36
|
+
gets
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Thing < Component
|
41
|
+
state :A, :B
|
42
|
+
start A
|
43
|
+
|
44
|
+
continuous :x
|
45
|
+
flow A do
|
46
|
+
diff "x' = 1"
|
47
|
+
end
|
48
|
+
|
49
|
+
transition A => B do
|
50
|
+
guard "x > 2"
|
51
|
+
end
|
52
|
+
|
53
|
+
transition B => A do
|
54
|
+
guard "x < 1e-10"
|
55
|
+
reset :x => 0
|
56
|
+
end
|
57
|
+
|
58
|
+
transition B => B do
|
59
|
+
guard "x >= 1e-10"
|
60
|
+
reset :x => "x-1"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
w = DebuggingWorld.new
|
65
|
+
|
66
|
+
w.create(Thing) do |th|
|
67
|
+
th.name = 1
|
68
|
+
th.x = 0.5
|
69
|
+
end
|
70
|
+
|
71
|
+
w.create(Thing) do |th|
|
72
|
+
th.name = 2
|
73
|
+
th.x = 5
|
74
|
+
th.start Thing::B
|
75
|
+
end
|
76
|
+
|
77
|
+
w.evolve 100
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'redshift'
|
2
|
+
|
3
|
+
class Population < RedShift::Component
|
4
|
+
flow do
|
5
|
+
diff " rabbits' = 0.3*rabbits - 0.02 * rabbits * foxes "
|
6
|
+
diff " foxes' = 0.01*foxes*rabbits - 0.5 * foxes "
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
world = RedShift::World.new do |w|
|
11
|
+
w.time_step = 0.05
|
12
|
+
end
|
13
|
+
|
14
|
+
pop = world.create Population
|
15
|
+
pop.foxes = 2
|
16
|
+
pop.rabbits = 100
|
17
|
+
|
18
|
+
data = []
|
19
|
+
world.evolve 100 do |w|
|
20
|
+
data << [w.clock, pop.foxes, pop.rabbits]
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'sci/plot'
|
24
|
+
include Plot::PlotUtils
|
25
|
+
|
26
|
+
gnuplot do |plot|
|
27
|
+
plot.command %{set title "Lotla-Volterra"}
|
28
|
+
plot.command %{set xlabel "time"}
|
29
|
+
plot.add data, %{using 1:2 title "foxes" with lines}
|
30
|
+
plot.add data, %{using 1:3 title "rabbits" with lines}
|
31
|
+
end
|
32
|
+
|
33
|
+
sleep 1 if /mswin32|mingw32/ =~ RUBY_PLATFORM
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'redshift'
|
2
|
+
require 'plot/plot'
|
3
|
+
require 'nr/random'
|
4
|
+
|
5
|
+
include RedShift
|
6
|
+
include NR::Random
|
7
|
+
include Math
|
8
|
+
|
9
|
+
|
10
|
+
class Ball < Component
|
11
|
+
|
12
|
+
flow {
|
13
|
+
euler " x' = @vx "
|
14
|
+
euler " y' = @vy "
|
15
|
+
}
|
16
|
+
|
17
|
+
defaults {
|
18
|
+
@x = 0
|
19
|
+
@y = 0
|
20
|
+
}
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
world = World.open "ball.world"
|
25
|
+
|
26
|
+
unless world
|
27
|
+
|
28
|
+
world = World.new {time_step 0.01}
|
29
|
+
|
30
|
+
seq = UniformSequence.new :min => 0, :max => 2*PI
|
31
|
+
|
32
|
+
5.times do
|
33
|
+
world.create(Ball) {
|
34
|
+
angle = seq.next
|
35
|
+
@vx = cos angle
|
36
|
+
@vy = sin angle
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
balls = world.select { |c| c.type == Ball }
|
43
|
+
|
44
|
+
data = {}
|
45
|
+
for b in balls
|
46
|
+
data[b] = [[b.x, b.y]]
|
47
|
+
end
|
48
|
+
|
49
|
+
50.times do
|
50
|
+
world.run
|
51
|
+
for b in balls
|
52
|
+
data[b] << [b.x, b.y]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Plot.new ('gnuplot') {
|
57
|
+
|
58
|
+
command 'set xrange [ -2 : 2 ]; set yrange [ -2 : 2 ]'
|
59
|
+
|
60
|
+
for b in balls
|
61
|
+
add data[b], "title \"#{balls.index(b)}\" with lines"
|
62
|
+
end
|
63
|
+
|
64
|
+
show
|
65
|
+
pause 5
|
66
|
+
}
|
67
|
+
|
68
|
+
world.save "ball.world"
|
data/examples/pid.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# PID control example
|
2
|
+
# See http://en.wikipedia.org/wiki/PID_control.
|
3
|
+
|
4
|
+
require 'redshift'
|
5
|
+
include RedShift
|
6
|
+
|
7
|
+
srand(12345)
|
8
|
+
|
9
|
+
# Variable with discrete and continuous perturbation.
|
10
|
+
class Plant < Component
|
11
|
+
continuous :x => 0, :t => 1
|
12
|
+
|
13
|
+
link :control => :Control # fwd ref to undefined class Control
|
14
|
+
|
15
|
+
flow do
|
16
|
+
diff " x' = control.output + sin(t) "
|
17
|
+
diff " t' = -1 "
|
18
|
+
end
|
19
|
+
|
20
|
+
transition do
|
21
|
+
guard "t <= 0"
|
22
|
+
action do
|
23
|
+
self.t += rand * 20
|
24
|
+
self.x += (rand - 0.5) * 10
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Tries to bring x back to the set_point.
|
30
|
+
class Control < Component
|
31
|
+
continuous :set_point => 2.0
|
32
|
+
continuous :p_out, :i_out, :d_out, :output
|
33
|
+
|
34
|
+
# Gains
|
35
|
+
constant :k_p => 1.0,
|
36
|
+
:k_i => 1.0,
|
37
|
+
:k_d => 1.0
|
38
|
+
|
39
|
+
link :plant => Plant
|
40
|
+
|
41
|
+
flow do
|
42
|
+
algebraic " error = set_point - plant.x "
|
43
|
+
algebraic " p_out = k_p * error "
|
44
|
+
differential " i_out' = k_i * error "
|
45
|
+
algebraic " d_out = k_d * (- sin(plant.t)) "
|
46
|
+
# since in plant we have x' = control.output + sin(t)
|
47
|
+
# and we can algebraically remove the "output" term.
|
48
|
+
# this is a special case that doesn't need numerical differentiation
|
49
|
+
algebraic " output = p_out + i_out + d_out "
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
world = World.new
|
54
|
+
plant = world.create Plant
|
55
|
+
control = world.create Control
|
56
|
+
control.plant = plant
|
57
|
+
plant.control = control
|
58
|
+
|
59
|
+
x, p_out, i_out, d_out, output = [], [], [], [], []
|
60
|
+
gather = proc do
|
61
|
+
time = world.clock
|
62
|
+
x << [time, plant.x]
|
63
|
+
p_out << [time, control.p_out]
|
64
|
+
i_out << [time, control.i_out]
|
65
|
+
d_out << [time, control.d_out]
|
66
|
+
output << [time, control.output]
|
67
|
+
end
|
68
|
+
|
69
|
+
gather.call
|
70
|
+
world.evolve 1000 do
|
71
|
+
gather.call
|
72
|
+
end
|
73
|
+
|
74
|
+
require 'sci/plot'
|
75
|
+
include Plot::PlotUtils
|
76
|
+
|
77
|
+
gnuplot do |plot|
|
78
|
+
plot.command %{set title "PID control"}
|
79
|
+
plot.command %{set xlabel "time"}
|
80
|
+
plot.add x, %{title "x" with lines}
|
81
|
+
plot.add p_out, %{title "p_out" with lines}
|
82
|
+
plot.add i_out, %{title "i_out" with lines}
|
83
|
+
plot.add d_out, %{title "d_out" with lines}
|
84
|
+
plot.add output, %{title "output" with lines}
|
85
|
+
end
|
86
|
+
|
87
|
+
sleep 1 if /mswin32|mingw32/ =~ RUBY_PLATFORM
|
data/examples/ports.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Shows how to use the port abstraction to refer to ports independently of the
|
2
|
+
# components (and classes) they are attached to.
|
3
|
+
|
4
|
+
require 'redshift'
|
5
|
+
include RedShift
|
6
|
+
|
7
|
+
class I < Component
|
8
|
+
flow do
|
9
|
+
diff " x' = -x "
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class A < Component
|
14
|
+
flow do
|
15
|
+
diff " t' = 1 "
|
16
|
+
alg " x = cos(t) "
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class K < Component
|
21
|
+
constant :x => 5.678
|
22
|
+
end
|
23
|
+
|
24
|
+
class W < Component
|
25
|
+
input :x
|
26
|
+
setup do
|
27
|
+
port(:x) << create(I).port(:x)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class L < Component
|
32
|
+
link :i => I
|
33
|
+
setup do
|
34
|
+
self.i = create(I)
|
35
|
+
end
|
36
|
+
flow do
|
37
|
+
alg " x = i.x "
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Tester < Component
|
42
|
+
input :x
|
43
|
+
end
|
44
|
+
|
45
|
+
w = World.new
|
46
|
+
|
47
|
+
comps = [I, A, K, W, L].map {|cl| w.create(cl)}
|
48
|
+
ports = comps.map {|comp| comp.port(:x)}
|
49
|
+
values = ports.map {|port| port.value}
|
50
|
+
|
51
|
+
p values # ==> [0.0, 1.0, 5.678, 0.0, 0.0]
|
52
|
+
|
53
|
+
tester = w.create(Tester)
|
54
|
+
values = ports.map do |port|
|
55
|
+
tester.port(:x) << port
|
56
|
+
tester.x
|
57
|
+
end
|
58
|
+
|
59
|
+
p values # same as above
|
60
|
+
|