y_petri 2.4.0 → 2.4.2
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.
- checksums.yaml +4 -4
- data/lib/y_petri/core.rb +13 -1
- data/lib/y_petri/core/timeless.rb +1 -6
- data/lib/y_petri/core/timeless/basic.rb +1 -1
- data/lib/y_petri/simulation/timed.rb +6 -2
- data/lib/y_petri/simulation/timeless.rb +34 -21
- data/lib/y_petri/version.rb +1 -1
- data/lib/y_petri/world/simulation_aspect.rb +5 -5
- data/test/core_test.rb +38 -1
- data/test/examples/issues.rb +71 -0
- data/test/examples/manual_examples.rb +2 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb7a7b5033fa23e8fbdaee627d1864722a31f850
|
4
|
+
data.tar.gz: b17971ab72080978c0877a281e6a22fd7dcef2df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df9453ff5bd03c744158b2d8f848c7700ea3cdc80f0c3eb6fb64c409a0436eb7bae5e7538ed86f96c3e759acd4b68c79d9b07cc0045bad0718d0ae7ea5d761ea
|
7
|
+
data.tar.gz: dd0569b0b5a0b402a78b1130b7805d3d8202ccd8219ddcdb35a18c7a10f4c479d12b4e4216f1a6c8cce84ff314ce18d228ab803e2f89d785682719d517901c2e
|
data/lib/y_petri/core.rb
CHANGED
@@ -75,7 +75,7 @@ module YPetri::Core
|
|
75
75
|
|
76
76
|
delegate :alert!, to: :recorder
|
77
77
|
|
78
|
-
# Delta
|
78
|
+
# Delta contribution to free places by timeless transitions.
|
79
79
|
#
|
80
80
|
def delta_timeless
|
81
81
|
delta_ts + delta_tS
|
@@ -112,6 +112,18 @@ module YPetri::Core
|
|
112
112
|
simulation.increment_marking_vector_closure.( delta )
|
113
113
|
end
|
114
114
|
|
115
|
+
# For now, alias method for #increment_marking_vector.
|
116
|
+
# TODO: I already said to myself that I want the core not to rely
|
117
|
+
# on the simulation's increment_marking_vector_closure.
|
118
|
+
#
|
119
|
+
def increment_free_vector( by: fail( "No delta given!" ) )
|
120
|
+
print '.'
|
121
|
+
simulation.increment_marking_vector_closure.( by )
|
122
|
+
# Also, here it is not clear that #increment_marking_vector_closure
|
123
|
+
# returns a closure that expects only Δ for free places. Should have
|
124
|
+
# better mnemonic name.
|
125
|
+
end
|
126
|
+
|
115
127
|
# Fires all the assignment transitions.
|
116
128
|
#
|
117
129
|
def fire_all_assignment_transitions!
|
@@ -31,10 +31,5 @@ class YPetri::Core::Timeless
|
|
31
31
|
delta_timeless # this method was taken from core.rb
|
32
32
|
# delta_ts + delta_tS # this is the contents of delta_timeless method
|
33
33
|
end
|
34
|
-
|
35
|
-
# Computes the system state delta.
|
36
|
-
#
|
37
|
-
def Δ
|
38
|
-
delta
|
39
|
-
end
|
34
|
+
alias Δ delta
|
40
35
|
end # module YPetri::Core::Timeless
|
@@ -10,7 +10,7 @@ module YPetri::Core::Timeless::Basic
|
|
10
10
|
def step!
|
11
11
|
# Compute the sum of the contribution of ts and tS transitions, and
|
12
12
|
# increment the free marking vector by it.
|
13
|
-
increment_free_vector by:
|
13
|
+
increment_free_vector by: Δ
|
14
14
|
# Fire all the assignment transitions in their order.
|
15
15
|
fire_all_assignment_transitions!
|
16
16
|
# before: assignment_transitions_all_fire!
|
@@ -349,9 +349,13 @@ module YPetri::Simulation::Timed
|
|
349
349
|
else
|
350
350
|
YPetri::Core::Timed.new( simulation: self, method: method, guarded: false )
|
351
351
|
end
|
352
|
+
# TODO: But why am I doing it like this? Did I want to emphasize the standalone
|
353
|
+
# nature of Core class? Maybe... And maybe I did it so that the runge-kutta method
|
354
|
+
# with its @rk_core instance variable instead of @core does not have @core and #core.
|
355
|
+
# In this manner, I'm forcing myself to rethink Simulation class.
|
352
356
|
singleton_class.class_exec do
|
353
357
|
attr_reader :core
|
354
|
-
delegate :simulation_method,
|
358
|
+
delegate :simulation_method, # this looks quite redundant with simulation.rb
|
355
359
|
:step!,
|
356
360
|
:firing_vector_tS,
|
357
361
|
to: :core
|
@@ -370,5 +374,5 @@ module YPetri::Simulation::Timed
|
|
370
374
|
else
|
371
375
|
Recorder().new( sampling: settings[:sampling] )
|
372
376
|
end
|
373
|
-
end
|
377
|
+
end # def init
|
374
378
|
end # module YPetri::Simulation::Timed
|
@@ -27,26 +27,39 @@ module YPetri::Simulation::Timeless
|
|
27
27
|
method = settings[:method] # the simulation method
|
28
28
|
features_to_record = settings[:record]
|
29
29
|
# Sets up a parametrized subclass of the sampler for timeless simulation.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
Recorder().new # init the recorder
|
50
|
-
end
|
30
|
+
param_class( { Recorder: Recorder }, with: { simulation: self } )
|
31
|
+
@core = if @guarded then
|
32
|
+
YPetri::Core::Timeless
|
33
|
+
.new( simulation: self, method: method, guarded: true )
|
34
|
+
else
|
35
|
+
YPetri::Core::Timeless
|
36
|
+
.new( simulation: self, method: method, guarded: false )
|
37
|
+
end
|
38
|
+
|
39
|
+
# TODO: But why am I doing it like this? Did I want to emphasize the standalone
|
40
|
+
# nature of Core class? Maybe... And maybe I did it so that the runge-kutta method
|
41
|
+
# with its @rk_core instance variable instead of @core does not have @core and #core.
|
42
|
+
# In this manner, I'm forcing myself to rethink Simulation class.
|
43
|
+
singleton_class.class_exec do
|
44
|
+
attr_reader :core
|
45
|
+
delegate :simulation_method, # this looks quite redundant with simulation.rb
|
46
|
+
:step!,
|
47
|
+
:firing_vector_tS,
|
48
|
+
to: :core
|
51
49
|
end
|
50
|
+
|
51
|
+
@recorder = if features_to_record then
|
52
|
+
# we'll have to figure out features
|
53
|
+
ff = case features_to_record
|
54
|
+
when Array then
|
55
|
+
net.State.Features
|
56
|
+
.infer_from_nodes( features_to_record )
|
57
|
+
when Hash then
|
58
|
+
net.State.features( features_to_record )
|
59
|
+
end
|
60
|
+
Recorder().new( features: ff )
|
61
|
+
else
|
62
|
+
Recorder().new # init the recorder
|
63
|
+
end
|
64
|
+
end # def init
|
52
65
|
end # module YPetri::Simulation::Timeless
|
data/lib/y_petri/version.rb
CHANGED
@@ -321,7 +321,7 @@ module YPetri::World::SimulationAspect
|
|
321
321
|
#
|
322
322
|
# * default_ss = { step_size: 0.1, sampling_period: 5, target_time: 60 }
|
323
323
|
#
|
324
|
-
def new_simulation( net: Net()
|
324
|
+
def new_simulation( net: Net().instance( :Top ), **nn )
|
325
325
|
net_inst = net( net )
|
326
326
|
nn.may_have :cc, syn!: :clamp_collection
|
327
327
|
nn.may_have :imc, syn!: :initial_marking_collection
|
@@ -330,13 +330,13 @@ module YPetri::World::SimulationAspect
|
|
330
330
|
imc_id = nn.delete( :imc ) || :Base
|
331
331
|
ssc_id = nn.delete( :ssc ) || :Base
|
332
332
|
# Construct the simulation key:
|
333
|
-
key = if nn.has? :name, syn!: :ɴ then
|
333
|
+
key = if nn.has? :name, syn!: :ɴ then # explicit key (name)
|
334
334
|
nn[:name]
|
335
|
-
else
|
335
|
+
else # constructed key
|
336
336
|
{}.merge( net: net_inst,
|
337
337
|
cc: cc_id,
|
338
|
-
|
339
|
-
|
338
|
+
imc: imc_id,
|
339
|
+
ssc: ssc_id )
|
340
340
|
.merge( nn )
|
341
341
|
end
|
342
342
|
# Let's clarify what we got so far.
|
data/test/core_test.rb
CHANGED
@@ -7,8 +7,10 @@ require_relative '../lib/y_petri' # tested component itself
|
|
7
7
|
# require 'y_petri'
|
8
8
|
# require 'sy'
|
9
9
|
|
10
|
-
describe "
|
10
|
+
describe "core" do
|
11
11
|
before do
|
12
|
+
@timed_core_class = YPetri::Core::Timed
|
13
|
+
@timeless_core_class = YPetri::Core::Timeless
|
12
14
|
# set up a user of core, which will imitate some of the needs
|
13
15
|
# of the Simulation class, or be an actual instance of that class
|
14
16
|
end
|
@@ -22,5 +24,40 @@ describe "use of timed and timeless core" do
|
|
22
24
|
# number of steps or until some other condition is fulfilled, or
|
23
25
|
# step backward, or even run backward, if the system allows such thing
|
24
26
|
# at all.
|
27
|
+
@timed_core_class::METHODS.keys.must_include :basic
|
28
|
+
@timeless_core_class::METHODS.keys.must_include :basic
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "timed core" do
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "timeless core" do
|
35
|
+
describe "basic method" do
|
36
|
+
before do
|
37
|
+
# @timeless_core_class.new( method: :basic )
|
38
|
+
# TODO: The above logically fails, because core now
|
39
|
+
# requires simulation. But newly, a core should no
|
40
|
+
# longer require a simulation. It should simply receive
|
41
|
+
# initial marking vector, information about places
|
42
|
+
# (including clamped places and their clamps), information
|
43
|
+
# above processes (ie. transitions). Surely, this looks
|
44
|
+
# like a third redundant layer of place and transition
|
45
|
+
# representations (the first two are in Net and Simulation
|
46
|
+
# class). But it serves me right since I want to do things
|
47
|
+
# properly :-) Core represents a simulation machine,
|
48
|
+
# hardware. Of course, I have no hardware other than
|
49
|
+
# Ruby itself. I am not even able to compile the simulation
|
50
|
+
# into C. It is quite imaginable that Simulation would
|
51
|
+
# be flexible about using cores and simulation methods
|
52
|
+
# to do what the user requires it to do, while cores would
|
53
|
+
# be more inflexible, method specific and machine specific.
|
54
|
+
# So Core is a machine abstraction, while Simulation is the
|
55
|
+
# abstraction of what the user might require from a Simulation.
|
56
|
+
# Anyway a good way to kill time.
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should behave" do
|
60
|
+
end
|
61
|
+
end
|
25
62
|
end
|
26
63
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
# Found things that do not work with YPetri.
|
4
|
+
|
5
|
+
require 'y_petri'
|
6
|
+
include YPetri
|
7
|
+
|
8
|
+
A = Place default_marking: 5
|
9
|
+
B = Place default_marking: 5
|
10
|
+
C = Place default_marking: 0
|
11
|
+
D = Place default_marking: 0
|
12
|
+
|
13
|
+
T1 = Transition stoichiometry: { A: -1, B: -1, C: 1 }
|
14
|
+
T2 = Transition stoichiometry: { C: -1, D: 1 }
|
15
|
+
|
16
|
+
net.timed? # The net is timeless
|
17
|
+
|
18
|
+
new_simulation # This produces timed simulation (same as run!)
|
19
|
+
|
20
|
+
net.simulation # While this produces timeless simulation.
|
21
|
+
|
22
|
+
# This is happening because I have deleted :core selector from
|
23
|
+
# Simulation class code. I did this because when adding Runge-Kutta
|
24
|
+
# method, I construct instance-specific instance variable @rk_core
|
25
|
+
# instead of @core.
|
26
|
+
|
27
|
+
# This, again, will produce timed simulation.
|
28
|
+
net.simulation **ssc
|
29
|
+
|
30
|
+
# Simulation#initialize has hard times deciding whether it is
|
31
|
+
# constructing timed or timeless simulation. When it sees time
|
32
|
+
# mentioned (:step, :sampling, :time parameters are all set)
|
33
|
+
# in ssc, it decides to construct a timed simulation.
|
34
|
+
#
|
35
|
+
# When it does not see the time mentioned, it decides to construct
|
36
|
+
# a timeless simulation. The decision is quite right when I merely
|
37
|
+
# call net.simulation, because the net is actually quite timeless.
|
38
|
+
#
|
39
|
+
# But once I call for :basic simulation method ...
|
40
|
+
#
|
41
|
+
# Now I used to call :basic method :pseudo_euler, which would suggest
|
42
|
+
# timed simulation. But timeless simulations also have :basic method
|
43
|
+
# among them...
|
44
|
+
#
|
45
|
+
# The question is whether I should have timed and timeless methods
|
46
|
+
# with same names...
|
47
|
+
|
48
|
+
# I should keep at this and rethink the Simulation class
|
49
|
+
|
50
|
+
# also, another problem
|
51
|
+
#
|
52
|
+
# set_ssc :Hello
|
53
|
+
#
|
54
|
+
# instead of trying to set the simulation settings collection
|
55
|
+
# to the one named :Hello will cause the simulation settings
|
56
|
+
# collection named :Base be set to :Hello
|
57
|
+
|
58
|
+
simulation_settings_collection # alias ssc
|
59
|
+
|
60
|
+
simulation_settings_collections
|
61
|
+
|
62
|
+
set_simulation_settings_collection :Hello
|
63
|
+
|
64
|
+
simulation_settings_collection # alias ssc
|
65
|
+
|
66
|
+
simulation_settings_collections
|
67
|
+
|
68
|
+
# This is obviously wrong. Whole idea of collections of clamps
|
69
|
+
# and initial values and simulation settings is quite dated, it
|
70
|
+
# dates back to the times when I was not at the top of my Ruby
|
71
|
+
# proficiency yet. Maybe time to rethink World / Agent classes.
|
@@ -9,7 +9,7 @@ set_step 10
|
|
9
9
|
set_target_time 600
|
10
10
|
set_sampling 10
|
11
11
|
# Euler with timeless transitions firing after each step:
|
12
|
-
set_simulation_method :
|
12
|
+
set_simulation_method :basic
|
13
13
|
|
14
14
|
A = Place m!: 1
|
15
15
|
B = Place m!: 10
|
@@ -25,4 +25,4 @@ Transition name: :C_held_at_half_B,
|
|
25
25
|
assignment: -> x { x / 2 }
|
26
26
|
|
27
27
|
run!
|
28
|
-
|
28
|
+
recording.plot
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: y_petri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.4.
|
4
|
+
version: 2.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- boris
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -253,6 +253,7 @@ files:
|
|
253
253
|
- test/examples/example_2.rb
|
254
254
|
- test/examples/example_IV.rb
|
255
255
|
- test/examples/example_VI_gillespie.rb
|
256
|
+
- test/examples/issues.rb
|
256
257
|
- test/examples/manual_examples.rb
|
257
258
|
- test/net_test.rb
|
258
259
|
- test/place_test.rb
|
@@ -305,6 +306,7 @@ test_files:
|
|
305
306
|
- test/examples/example_2.rb
|
306
307
|
- test/examples/example_IV.rb
|
307
308
|
- test/examples/example_VI_gillespie.rb
|
309
|
+
- test/examples/issues.rb
|
308
310
|
- test/examples/manual_examples.rb
|
309
311
|
- test/net_test.rb
|
310
312
|
- test/place_test.rb
|